Want to understand async

I used asynchronous coding a bit, but I don’t quite understand how to use it, although I understand the concept and why I need it.

Here is my setup:

I have a web API that I will call from my ASP.NET MVC application, and my web API will call DocumentDB. In the code samples, I see a lot of pending keywords when sending requests to DocumentDB.

Am I confused if I need to do my index action method in my asynchronous MVC application? Am I also confused if my CreateEmployee () method in my web interface should be asynchronous?

What is the correct way to use async in this scenario?

Here is my code (this code is currently giving me errors because my MVC action method is not asynchronous) ---- ASP.NET MVC Application Code ----

public ActionResult Index() { Employee emp = new Employee(); emp.FirstName = "John"; emp.LastName = "Doe"; emp.Gender = "M"; emp.Ssn = "123-45-6789"; using (var client = new HttpClient()) { client.BaseAddress = new Uri("http://myWebApi.com"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.PostAsJsonAsync("hr/create/newemployee", emp); if (response.IsSuccessStatusCode) { emp = await response.Content.ReadAsAsync<Employee>(); } } // Display employee info return View(emp); } 

---- Web API Code ----

 private static readonly string endPointUrl = ConfigurationManager.AppSettings["EndPointUrl"]; private static readonly string authorizationKey = ConfigurationManager.AppSettings["AuthorizationKey"]; private static readonly string databaseId = ConfigurationManager.AppSettings["DatabaseId"]; private static DocumentClient client; public static async Task<Employee> CreateEmployee(Employee emp) { try { //Create a Document client using (client = new DocumentClient(new Uri(endPointUrl), authorizationKey)) { //Get the database var database = await GetDatabaseAsync(); //Get the Document Collection var collection = await GetCollectionAsync(database.SelfLink, "Employees"); await client.CreateDocumentAsync(collection.SelfLink, emp); // Further process employee } } catch { // Handle error } return employee; } private static async Task<DocumentCollection> GetCollectionAsync(string dbLink, string id) { DocumentCollection collection = client.CreateDocumentCollectionQuery(dbLink).Where(c => c.Id == id).ToArray().FirstOrDefault(); return collection; } private static async Task<Database> GetDatabaseAsync() { Database database = client.CreateDatabaseQuery().Where(db => db.Id == databaseId).ToArray().FirstOrDefault(); return database; } 
+6
c # async-await asp.net-web-api2 azure-cosmosdb
source share
3 answers

you can use await only inside the method if this async and async method should return the Task , Task<T> or void methods, although the void return async methods are reserved for event handlers because the exceptions thrown inside them are swallowed and you cannot await complete their completion or a chain of subsequent tasks.

I think your Index action should be async and return Task<ActionResult> , and your CreateEmployee method should be async and also use await inside it.

See Asynchronous Programming Guidelines for some guidelines on when and how to use async-await

+6
source share

Here is my explanation

 class MainClass { public static async Task<String> AsyncMethod(int delay) { await Task.Delay (TimeSpan.FromSeconds(delay)); return "The method has finished it execution after waiting for " + delay + " seconds"; } public static async Task Approach1(int delay) { var response = await AsyncMethod (delay); // await just unwraps Task result Console.WriteLine (response); } public static Task Approach2(int delay) { return AsyncMethod(delay).ContinueWith(message => Console.WriteLine(message)); // you could do the same with } public static void Main (string[] args) { var operation1 = Approach1 (3); var operation2 = Approach2 (5); Task.WaitAll (operation1, operation2); Console.WriteLine("All operations are completed") } } 

Ultimately, both Approach1 and Approach2 are identical pieces of code.

async/await - syntax sugar around Task API. This async method breaks it into pieces before await and after await . The "before" part is executed immediately. After the await operation is completed, the after command is executed. You can track the second part of the operation through the Task API, as you get a link to the task.

In general, async allows you to treat a method call as some long operation that you can reference through the Task API, and wait until it is finished, and continue with the other part of the code. Or through ContinueWith calling through with await is generally the same.

Before async / await / Task concepts used callbacks, but error handling was as simple as hell, Task is similar to the concept of callback , except that it makes handling exceptions easier.

In general, all this Task / async / await mantra is close to the concept of promises , if it happens when you worked with jQuery / JavaScript, there is a similar concept, there is a good question explaining how it is done there " jQuery is postponed and promises - .then () vs .done () "


Change I just found out that .NET does not have an implementation of then functionality similar to that found in jQuery / JavaScript.

The difference between ContinueWith and then is that then is able to compose the task and execute it sequentially, while ContinueWith is not, it can run the task in parallel, but this can be easily implemented through the wait construct. Here is my updated code containing the entire shebang:

 static class Extensions { // Implementation to jQuery-like `then` function in .NET // According to: http://blogs.msdn.com/b/pfxteam/archive/2012/08/15/implementing-then-with-await.aspx // Further reading: http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx public static async Task Then(this Task task, Func<Task> continuation) { await task; await continuation(); } public static async Task<TNewResult> Then<TNewResult>( this Task task, Func<Task<TNewResult>> continuation) { await task; return await continuation(); } public static async Task Then<TResult>( this Task<TResult> task, Func<TResult,Task> continuation) { await continuation(await task); } public static async Task<TNewResult> Then<TResult, TNewResult>( this Task<TResult> task, Func<TResult, Task<TNewResult>> continuation) { return await continuation(await task); } } class MainClass { public static async Task<String> AsyncMethod1(int delay) { await Task.Delay (TimeSpan.FromSeconds(delay)); return "The method has finished it execution after waiting for " + delay + " seconds"; } public static Task<String> AsyncMethod2(int delay) { return Task.Delay (TimeSpan.FromSeconds (delay)).ContinueWith ((x) => "The method has finished it execution after waiting for " + delay + " seconds"); } public static async Task<String> Approach1(int delay) { var response = await AsyncMethod1 (delay); // await just unwraps Task result return "Here is the result of AsyncMethod1 operation: '" + response + "'"; } public static Task<String> Approach2(int delay) { return AsyncMethod2(delay).ContinueWith(message => "Here is the result of AsyncMethod2 operation: '" + message.Result + "'"); } public static void Main (string[] args) { // You have long running operations that doesn't block current thread var operation1 = Approach1 (3); // So as soon as the code hits "await" the method will exit and you will have a "operation1" assigned with a task that finishes as soon as delay is finished var operation2 = Approach2 (5); // The same way you initiate the second long-running operation. The method also returns as soon as it hits "await" // You can create chains of operations: var operation3 = operation1.ContinueWith(operation1Task=>Console.WriteLine("Operation 3 has received the following input from operation 1: '" + operation1Task.Result + "'")); var operation4 = operation2.ContinueWith(operation2Task=>Console.WriteLine("Operation 4 has received the following input from operation 2: '" + operation2Task.Result + "'")); var operation5 = Task.WhenAll (operation3, operation4) .Then(()=>Task.Delay (TimeSpan.FromSeconds (7))) .ContinueWith((task)=>Console.WriteLine("After operation3 and 4 have finished, I've waited for additional seven seconds, then retuned this message")); Task.WaitAll (operation1, operation2); // This call will block current thread; operation3.Wait (); // This call will block current thread; operation4.Wait (); // This call will block current thread; operation5.Wait (); // This call will block current thread; Console.WriteLine ("All operations are completed"); } } 
+6
source share
 async await 

They are hard to understand.

First of all, in your methods in the Web API, you use async without waiting. I'm sure you get some errors / warning there right?

-

async await is used to return the workflow back to the caller when you wait for I / O to complete. So yes, you want to use it in both your MVC and web API. Please make sure you understand this offer before moving on.

-

The thing about async / await is that if you use it, you must use it ALL through the calling functions, otherwise it does not make sense (and you will also get errors / warning). This means that any library that you use must support it. In this case, "DocumentClient". By convention, methods that support it end in Async and it will return the job you can expect.

-

So, your short answer: use async from the very beginning (your controller) and try to make it perform lengthy operations. If this is your code, you should be able to wait from there ... and wait from there ... until you finally name something that is not your code. If you can wait for this code that does not belong to you, then you are set up. If you cannot do this, you should not use async waiting from the start.

(that didn't make sense)

+1
source share

All Articles