This question already has an answer here:
EF6 two contexts vs. single context with two awaits
(1 answer)
Closed 4 years ago.
After going through a lot of articles and videos i am still having problem with the asynchronous programming.I am working on a project where in service layer I have created all the methods as async. All of the return Task <T> or Task (I made sure not to return void).
Now to the issue. My Api calls async methods which internally calls other async methods which may even call other async methods. So I await every time I encounter an async method.
The downside with this approach, I think, is that cause I am awaiting for result every time I encounter async it will take a lot of time. For ex:
public async Task<xyz> DoMainTask(int ActionId, int ItemId, int UserId)
{
await DoTask1(ActionId,ItemId,UserId); 3 sec
await DoTask2(ActionId,ItemId,UserId); 3 sec
await DoTask3(ActionId,ItemId,UserId); 3 sec
}
So I don't want to wait for 9 sec because all tasks here are independent of each other.
I want to do something like:
public async Task<xyz> DoMainTask(int ActionId, int ItemId, int UserId)
{
List<Task> lst = new List<Task>();
t1= DoTask1(ActionId,ItemId,UserId);
lst.Add(t1);
t2 = DoTask2(ActionId,ItemId,UserId);
lst.Add(t2);
t3 = DoTask3(ActionId,ItemId,UserId);
lst.Add(t3);
await Task.WhenAll(lst);
// do some work
return xyz;
}
Which will probably take around 5-6 sec. How do I do this?
Whenever I try to use 2nd approach it get error:
A second operation started on this context before a previous asynchronous operation completed
DoTask1 is defined as:
public async Task DoTask1 (int ActionId, int ItemId, int UserId)
{
try
{
DailyActivityPoint dailyActivityPoint = new DailyActivityPoint()
{
ActionId = ActionId,
CreatedDate = DateTime.Now,
ItemId = ItemId,
UserId = UserId,
PointsAccumulated = await GetPointsAwardedForAction(ActionId)
};
_entities.DailyActivityPoints.Add(dailyActivityPoint);
await _entities.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
inside DoTask1 I am also calling an async method.
How can it be done and what's the best practice?
I believe you are encountering a thread-safety concern as described here. If so, you'll need to be sure that for each 'awaitable' that reaches into EF it is using its own DbContext instance.
So, be sure you aren't using a DbContext singleton; instantiate a new one as you go if you can or get tricky with a container like he does in the link (containers are your friends)
Maybe you should use this guideline in writing your asynchronous methods
Guideline:
Write the method the normal way you would write a conventional method, then convert it to an async method.
Use the async keyword in the method declaration.
public async Task<int> ExampleMethodAsync()
{
// . . . .
}
Use the await keyword in the code calling an asynchronous process/method.
int resultValue = await ExampleMethodAsync();
Note: await can only be used in an async method modified by the async keyword.
Use one of the correct return types in the async method in order to get results
return types for an async method need to be one of the following:
Task if your method has a return statement in which the operand has type TResult.
Task if your method has no return statement or has a return statement with no operand.
void if you're writing an async event handler.
Adding the “Async” suffix at the end of the calling method name. This is not required but is considered
a convention for writing async methods in C#.
public async Task<int> ExampleCallingMethodAsync()
{
// . . . .
}
Include at least one await expression in the async method code.
The suspension of an async method at an await expression doesn't
constitute an exit from the method, and finally blocks don’t run.
public async Task<int> ExampleMethodAsync()
{
//some code
string pageContents = await client.GetStringAsync(uri);
//some more code
return pageContents.Length;
}
Note:
You have to adjust what your async method is returning. The object being returned has to match the type Task<T> of your async method
If an async method doesn’t use an await operator to mark a suspension point, the method
executes as a synchronous method does, despite the async modifier. The compiler issues a
warning for such methods.
Below is a typical method converted to an asynchronous method
Example
private void WebPage(string someURI)
{
WebClient webClient = new WebClient();
string pageContent = webClient.DownloadString(someURI);
Console.WriteLine(pageContent);
}
changed to:
private async void WebPageAsync(string someURI)
{
WebClient webClient = new WebClient();
string pageContent = await webClient.DownloadStringTaskAsync(someURI);
Console.WriteLine(pageContent);
}
I hope this was helpful?
Related
This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
How and when to use ‘async’ and ‘await’
(25 answers)
Closed 3 years ago.
I was looking at how to use async await, but I do not quite get it when we have multiple methods invoking each other. Should we always use await or should we only use await when we are actually ready to use the result?
So for example should we do it like this:
async Task<string[]> FooAsync()
{
var info = await Func1();
return info.split('.');
}
async Task<string> Func1()
{
return await Func2();
}
async Task<string> Func2()
{
return await tcpClient.ReadStringAsync();
}
Or like this:
async Task<string[]> FooAsync()
{
var info = await Func1();
return info.split('.');
}
Task<string> Func1()
{
return Func2();
}
Task<string> Func2()
{
return tcpClient.ReadStringAsync();
}
Per example 1, should we always use await in every method?
Or
Per example 2 should we only use await on the top-most method when we start using the result?
Every-time you call await it creates a lump of code to bundle up variables, captures the synchronization context (if applicable) and create a continuation into an IAsyncStateMachine.
Essentially, returning a Task without the async keyword will give you a small run-time efficiency and save you a bunch of CIL. Do note that the Async feature in .NET also has many optimizations already. Also note (and importantly) that returning a Task in a using statement will likely throw an Already Disposed Exception.
You can compare the CIL and plumbing differences here
Forwarded Task
Async Method
So if your method is just forwarding a Task and not wanting anything from it, you could easily just drop the async keyword and return the Task directly.
More-so, there are times when we do more than just forwarding and there is branching involved. This is where, Task.FromResult and Task.CompletedTask come into play to help deal with the logic of what may arise in a method. I.e If you want to give a result (there and then), or return a Task that is completed (respectively).
Lastly, the Async and Await Pattern has subtle differences when dealing with Exceptions. If you are returning a Task, you can use Task.FromException<T> to pop any exception on the the returned Task like an async method would normally do.
Nonsensical example
public Task<int> DoSomethingAsync(int someValue)
{
try
{
if (someValue == 1)
return Task.FromResult(3); // Return a completed task
return MyAsyncMethod(); // Return a task
}
catch (Exception e)
{
return Task.FromException<int>(e); // Place exception on the task
}
}
In short, if you don't quite understand what is going on, just await it; the overhead will be minimal. However, if you understand the subtitles of how to return a task result, a completed task, placing an exception on a task, or just forwarding. You can save your self some CIL and give your code a small performance gain by dropping the async keyword returning a task directly and bypassing the IAsyncStateMachine.
At about this time, I would look up the Stack Overflow user and author Stephen Cleary, and Mr. Parallel Stephen Toub. They have a plethora of blogs and books dedicated solely to the Async and Await Pattern, all the pitfalls, coding etiquette and lots more information you will surely find interesting.
Both options are legit and each option has own scenarios where it is more effective then another.
Of course always use await when you want to handle result of the asynchronous method or handle possible exception in current method
public async Task Execute()
{
try
{
await RunAsync();
}
catch (Exception ex)
{
// Handle thrown exception
}
}
If you don't use result of asynchronous method in current method - return the Task. This approach will delay state machine creation to the caller or where ever final task will be awaited. As pointed in the comments can make execution little bit more effective.
But there are scenarios where you must await for the task, even you do nothing with result and don't want handle possible exceptions
public Task<Entity> GetEntity(int id)
{
using (var context = _contextFactory.Create())
{
return context.Entities.FindAsync(id);
}
}
In the scenario above, FindAsync can return not completed task and this task will be returned straight away to the caller and dispose context object created within using statement.
Later when caller will "await" for the task exception will be thrown because it will try to use already disposed object(context).
public async Task<Entity> GetEntity(int id)
{
using (var context = _contextFactory.Create())
{
return await context.Entities.FindAsync(id);
}
}
And traditionally answers about Async Await must include link to Stephen Cleary's blog
Eliding Async and Await
Await is a sequencing feature which allows the caller to receive the result of an async method and do something with it. If you do not need to process the result of an async function, you do not have to await it.
In your example Func1() and Func2() do no process the return values of the called async functions, so it is fine not to await them.
When you use await the code will wait for the async function to finish. This should be done when you need a value from an async function, like this case:
int salary = await CalculateSalary();
...
async Task<int> CalculateSalary()
{
//Start high cpu usage task
...
//End high cpu usage task
return salary;
}
If you hadn't use the the await this would happen:
int salary = CalculateSalary().Result;
...
async Task<int> CalculateSalary()
{
//Start high cpu usage task
... //In some line of code the function finishes returning null because we didn't wait the function to finish
return salary; //This never runs
}
Await means, wait this async function to finish.
Use it to your needs, your case 1 and 2 would produce the same result, as long as you await when you assign the info value the code will be safe.
Source: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index
I believe the 2nd one will do because await is expecting a return value.
Since it is waiting for the Func1() to return a value, Func1() is already executing Func2() which is returning a value.
My async method is as below:
public async Task<List<object>> handleSummaryOfWallets()
{
string token = giveMeToken("URL AND CREDS");
Channel channel = new Channel("NANANANA GIROUD", ChannelCredentials.Insecure);
OMGadminAPI.OMGadminAPIClient client = new OMGadminAPI.OMGadminAPIClient(channel);
var summaryBalancesParams = new OMGadminAPIGetCurrenciesSummariesParams();
summaryBalancesParams.AdminAuthTokenSecret = token;
List<object> summariesCurrenciesOMGadmin = new List<object>();
using (var call = client.GetCurrenciesSummaries(summaryBalancesParams))
{
while (await call.ResponseStream.MoveNext())
{
OMGadminAPICurrencySummary currencySummary = call.ResponseStream.Current;
summariesCurrenciesOMGadmin.Add(currencySummary);
Console.WriteLine(summariesCurrenciesOMGadmin);
}
return summariesCurrenciesOMGadmin;
}
}
As you can see, above async method returns list of objects. I call this method as below:
var listOfBalances = balances.handleSummaryOfWallets().Wait();
and it gives me error:
Error CS0815: Cannot assign void to an implicitly-typed variable
From the error, I understand that this is not correct way to call async method. But I need to read ready list of objects from async fetched data. Its request-response, no real stable stream. So I need to generate this list only once per request. I'm using gRPC framework for RPC calls.
Please help me fetch this data and make ready to use.
The Task.Wait method waits for the Task to complete execution. It returns void. That is the reason why the exception.
Now to overcome the exception and to read the return value, one way is as mentioned in other answer and the comments; await the call as below:
public async void TestAsync()
{
var listOfBalances = await handleSummaryOfWallets();
}
Note that your calling method should also be async method now.
As you are calling Wait in your code, it looks that you want the result immediately; you have nothing else left to do that does not depend on result. In that case, you may choose to stop async chain by calling Wait. But you need to do some changes as below:
public void TestAsync()
{
var task = handleSummaryOfWallets();//Just call the method which will return the Task<List<object>>.
task.Wait();//Call Wait on the task. This will hold the execution until complete execution is done.
var listOfBalances = task.Result;//Task is executed completely. Read the result.
}
Note that calling method is no longer async. Other explanation is given in code-comments.
Other short alternative to above code is as below:
public void TestAsync()
{
var listOfBalances = handleSummaryOfWallets().Result;
}
Just use await while calling your method
var listOfBalances = await balances.handleSummaryOfWallets();
As experiencing the new async & Await features of 4.5 I want to clear some confusions before going any further. I have been reading different article and also different question on SO and it help me undertands how Async and Await works. I will just try to put my understanding and confusions here and will appreciate if someone code educate me and other people who are looking for same things. I am discussing this in very simple wordings.
So Async is used so that compiler know that method marked by Async contains Await operation (Long operation). Latest framework contains different new builtin methods for Async Operations.
The builtin Async functions like connection.OpenAsync, ExecuteScalarAsync etc are used with Await keyword. I don't know the inner working of these Async Methods but my strong guess is that under the hood they are using Tasks.
Can I make this as general rule that Await will be with any method which implements Task. So if I need to create my own method which is performing long operation then will I create it as Task and when it is called I will use Await Keyword with it?
Second most important thing is that what is the rule of thumb of creating a method as Async or creating it as task. For example,
public void SampleMain()
{
for (int i = 1; i <= 100; i++)
{
DataTable dt = ReadData(int id);
}
}
public DataTable ReadData(int id)
{
DataTable resultDT = new DataTable();
DataTable dt1 = new DataTable();
// Do Operation to Fill DataTable from first connection string
adapter.Fill(dt1);
DataTable dt2 = new DataTable();
// Do Operation to Fill DataTable from first connection string
adapter.Fill(dt2);
// Code for combining datatable and returning the resulting datatable
// Combine DataTables
return resultDT;
}
public string GetPrimaryConnectionString()
{
// Retrieve connection string from some file io operations
return "some primary connection string";
}
public string GetSecondaryConnectionString()
{
// Retrieve connection string from some file io operations
return "some secondaryconnection string";
}
Now this is a very simple scenario that I have created based on some real world application I worked in past. So I was just wondering how to make this whole process Async.
Should I make GetPrimaryConnectionString and GetSecondaryConnectionString as Tasks and Await them in ReadData. Will ReadData be also a Task? How to call ReadData in the SampleMain function?
Another way could be to create a Task for ReadData in SampleMain and run that Task and skip converting other methods as Task. Is this the good approach? Will it be truly Asynchronous?
So Async is used so that compiler know that method marked by Async
contains Await operation
The async is used so that the compiler will have an indication to create a state-machine out of the method. An async method can have no await, and still work, though it will execute completely synchronously.
The builtin Async functions like connection.OpenAsync,
ExecuteScalarAsync etc are used with Await keyword. I don't know the
inner working of these Async Methods but my strong guess is that under
the hood they are using Tasks.
Task is a promise of work to be completed in the future. There are a couple of ways to create a Task. But, Task isn't the only thing that can be represent an asynchronous operation. You can create an awaitable yourself if you wanted, all it needs it to implement a GetAwaiter method which returns a type implementing INotifyCompletion.
If you want to know how a method is implemented in the framework, you can view the source. In this particular case, they use TaskCompletionSource<T>.
Should I make GetPrimaryConnectionString and
GetSecondaryConnectionString as Tasks and Await them in ReadData. Will
ReadData be also a Task? How to call ReadData in the SampleMain
function?
There is nothing inherently asynchronous about retrieving a connection string. You usually (not always) use async-await with naturally async IO operations. In this particular case, the only actual async operation is ReadData, and if you want to make it asynchronous, you can use SqlDataReader, which exposes async methods.
An example, taken from the ADO.NET teams blog:
public static async Task<Product> GetProductAndReviewsAsync(
int productID, int reviewsToGet)
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
await connection.OpenAsync();
const string commandString = GetProductByIdCommand + ";"
+ GetProductReviewsPagedById;
using (SqlCommand command = new SqlCommand(commandString, connection))
{
command.Parameters.AddWithValue("productid", productID);
command.Parameters.AddWithValue("reviewStart", 0);
command.Parameters.AddWithValue("reviewCount", reviewsToGet);
using (SqlDataReader reader = await command.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
Product product = GetProductFromReader(reader, productID);
if (await reader.NextResultAsync())
{
List<Review> allReviews = new List<Review>();
while (await reader.ReadAsync())
{
Review review = GetReviewFromReader(reader);
allReviews.Add(review);
}
product.Reviews = allReviews.AsReadOnly();
return product;
}
else
{
throw new InvalidOperationException(
"Query to server failed to return list of reviews");
}
}
else
{
return null;
}
}
}
}
}
how to make this whole process Async
If there are asynchronous versions of adapter.Fill, then simply await for it in ReadData, which in turn also become async and you can await for it in the caller method:
// in async button click event
button.Enabled = false;
var dt = await ReadData(int id);
button.Enabled = true;
... // do something with dt
public async Task<DataTable> ReadData(int id)
{
...
var job1 = adapter.AsyncFill(dt1);
var job2 = adapter.Fill(dt2);
// wait for all of them to finish
Task.WaitAll(new[] {job1, job2});
...
return Task.FromResult(resultDT); // dump approach
}
If there are no asynchronous version then you have to create them (by using Task):
// in async button click event
button.Enabled = false;
// run synchronous task asynchronously
var dt = await Task.Run(() => ReadData(int id));
button.Enabled = true;
... // do something with dt
async/await shines when it comes to UI, otherwise (if no UI is involved) just create task and run synchronous operation there.
The only reason to use async-await is if your main thread might do something useful while another thread is doing the length operation. If the main thread would start the other thread and only wait for the other thread to finish, it is better to let the main thread do the action.
One of the things a main thread quite often does is keep the UI responsive.
You are right, under the hood async-await uses Task, hence you see that an async function returns a Task.
The rules:
If a function would return void, the async version returns Task. If the function would return TResult, the async version should return Task<TResult>.
There is one exception: the async event handler returns void.
The return value of await Task is void. The return value of await Task<TResult> is TResult.
Only async functions can call other async functions.
If you have a non-async function you can still use the async function. However you cannot use await. Use the Task return value of the async function and the System.Threading.Tasks.Task methods to wait for the results.
If you have an async function and want to start a non-async function in a separate thread, use:
private int SlowCalculation(int a, int b)
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
return a + b;
}
private async Task CalculateAsync(int a, int b)
{
Task myTask = Task.Run( () => SlowCalculation(a, b);
// while SlowCalcuation is calculating slowly, do other useful things
// after a while you need the answer
int sum = await myTask;
return sum;
}
See that the return of await Task<int> is int.
Some people used to use functions like Task.ContinueWith. Because of the await statement that is not needed anymore. Await makes sure that the task is finished. The statement after the await is what you'd normally do in the ContinueWith.
In Task.ContinueWith you could say: "do this only if the task failed". The async-await equivalent for this is try-catch.
Remember: if your thread has nothing useful to do (like keeping your UI responsive), don't use async-await
Starting several tasks in async-await and waiting for them to finish is done as follows:
private async Task MyAsyncFunction(...)
{
var tasks = new List<Task<int>>();
for (int i=0; i<10; ++i)
{
tasks.Add(CalculateAsync(i, 2*i);
}
// while all ten tasks are slowly calculating do something useful
// after a while you need the answer, await for all tasks to complete:
await Task.WhenAll(tasks);
// the result is in Task.Result:
if (task[3].Result < 5) {...}
}
The async-await version of Task.Waitall is Task.WhenAll. WhenAll returns a Task instead of void, so you can await for it. The main thread remains responsive even while awaiting.
The main thread is not the case when using Task.WaitAll, because you don't await.
In this example from Microsoft, the method has a return type of Task<int>
Example 1:
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
In this second example, it uses async and await, BUT doesn't return a type of Task<>, why?
Example 2:
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
ReadCharacters();
}
static async void ReadCharacters()
{
String result;
using (StreamReader reader = File.OpenText("existingfile.txt"))
{
Console.WriteLine("Opened file.");
result = await reader.ReadToEndAsync();
Console.WriteLine("Contains: " + result);
}
}
}
}
Third, in the first example, is it possible to return an array(strings)?
In this second example, it uses async and await, BUT doesn't return a
type of Task<>, why?
They made an error. Whenever you create a method which is async and doesn't have a return value, it should return a Task. The only exception to that is event handlers, where you need to keep compatibility with the delegates signature, but this isn't the case. Think of a Task as the void equivalent of asynchronous methods.
Why do you actually want to return a Task and not void? Because returning a Task allows you to monitor the status of execution, and also lets you to properly handle any exceptions encapsulated inside the on going operation.
For example, think of an async void method that throws:
public async void WaitAndThrowAsync()
{
await Task.Delay(1000);
throw new Exception("yay");
}
public void CallWaitAndThrowAsync()
{
// What happens when it throws here?
WaitAndThrowAsync();
}
When you invoke this, you have no way to actually handle exceptions happening inside the method, it is "fire and forget" for the call-site. But when you expose a Task, you can now better handle that exception by asynchronously waiting:
public async Task WaitAndThrowAsync()
{
await Task.Delay(1000);
throw new Exception("yay");
}
public async Task CallWaitAndThrowAsync()
{
try
{
await WaitAndThrowAsync();
}
catch (Exception e)
{
// Do something.
}
}
Third, in the first example, is it possible to return an
array(strings)?
Yes, by returning a Task<string[]>:
public async Task<string> GetArrayAsync()
{
HttpClient client = new HttpClient();
var responseStream = await client.GetStreamAsync("http://msdn.microsoft.com");
using (var streamReader = new StreamReader(responseStream))
{
return await streamReader.ReadToEndAsync();
}
}
When you mark a method async, the compiler will implicitly create a Task for you. When you have a return type, the generated task is a Task<T> where T is your return type.
The second example is not a good example: with async void it's not possible anymore to await the asynchronous method. async void should be used for event handlers only.
For your second question, yes it's possible to return an array of strings.
Just use Task<string[]>.
I really recommend you to read this excellent article from Stephen Cleary: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
Some best practices from the article:
Avoid async void: Prefer async Task methods over async void methods. Exceptions: Event handlers
Async all the way: Don’t mix blocking and async code. Exceptions: Console main method
That second isn't according to the guidelines specified by Microsoft:
The return type is one of the following types:
- Task if your method has a return statement in which the operand has type TResult.
- Task if your method has no return statement or has a return statement with no operand.
- Void (a Sub in Visual Basic) if you're writing an async event handler.
Why should methods return Task or Task<T>?
Each returned task represents ongoing work. A task encapsulates information about the state of the asynchronous process and, eventually, either the final result from the process or the exception that the process raises if it doesn't succeed.
So you lose information when you use void. You discard the actual task progress and execution information. So for the void return type, use Task. For any other type, use Task<T>, where T is the actual return type.
Some methods can return void, but that is prohibited to event handler or starter methods:
An async method can also be a Sub method (Visual Basic) or have a void return type (C#). This return type is used primarily to define event handlers, where a void return type is required. Async event handlers often serve as the starting point for async programs.
I've used async coding a little bit but I don't really fully understand how to use it -- though I understand the concept and why I need it.
Here's my set up:
I have a Web API that I will call from my ASP.NET MVC app and my Web API will call DocumentDB. In code samples, I see a lot of await keywords while sending queries to DocumentDB.
I'm confused if I need to make my Index action method in my MVC app async?
I'm also confused if my CreateEmployee() method in my Web API should be async?
What is the right way to use async in this scenario?
Here's my code (This code is currently giving me errors because my MVC action method is not async)
---- ASP.NET MVC App 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;
}
Here's my explanation
class MainClass
{
public static async Task<String> AsyncMethod(int delay) {
await Task.Delay (TimeSpan.FromSeconds(delay));
return "The method has finished it's execution after waiting for " + delay + " seconds";
}
public static async Task Approach1(int delay)
{
var response = await AsyncMethod (delay); // await just unwraps Task's 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")
}
}
Eventually both Approach1 and Approach2 are identical pieces of code.
The async/await is syntactic sugar around Task API. It takes your async method splits it into parts before await, and after await. The "before" part is executed immediately. The "after" part is getting executed when await operation is completed. You are able to track the second part of operation via the Task API since you get a reference to a Task.
In general async allows to treat a method call as a some sort of long operation that you can reference via the Task API and wait until it is finished and continue with another piece of code. Either via ContinueWith call of via using await in general it's the same.
Before async/await/Task concepts people were using callbacks, but handling errors was as easy as hell, the Task is similar to a concept of callback except that it is able allow handling exceptions more easily.
In general all this Task/async/await mantra is close to concept of promises if it happen that you've worked with jQuery/JavaScript there's a similar concept here's a nice question explaining how it's done there "jQuery deferreds and promises - .then() vs .done()"
Edit: I've just found out that .NET lacks implementation of then functionality similar to one found in jQuery/JavaScript.
The difference between ContinueWith and Then is that Then is able to compose task, and to execute them sequentially while ContinueWith is not, it is able only to launch task in parallel, but it can be easily implemented via the await construct. Here is my updated code containing the whole 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's 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's execution after waiting for " + delay + " seconds");
}
public static async Task<String> Approach1(int delay)
{
var response = await AsyncMethod1 (delay); // await just unwraps Task's 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");
}
}
you can only use await inside a method if that method is async and async methods need to return Task, Task<T> or void although void returning async methods are reserved for event handlers because the exceptions thrown within them are swallowed and you cannot await their completion or chain subsequent tasks.
I think your Index action needs to be async and return a Task<ActionResult> and your CreateEmployee method needs to be async as well as it is using await inside it.
See Best Practices in Asynchronous Programming for some guidelines on when and how to use async-await
async await
They are tricky to understand.
First of all, in your methods in Web API, you are using async without await. I'm sure you are getting some errors / warning there right?
--
async await are used to return the working thread back to the caller when you are waiting for I/O to be finished. So, yes, you do want to use it both in your MVC and Web API side. Please make sure you understand this sentence before moving on.
--
The thing about async / await is that, if you use it, you have to use it ALL the way through the calling functions, or else it doesn't make sense (and you'll get errors / warning too). This means that whatever library you are using must support it. In this case "DocumentClient". By convention, the methods that support it will end in "Async" and it will return a Task which you can await.
--
So your short answer:
use async await from the very beginning (your controller), and try to make it await whatever long operations it calls. If that is also your code, you should be able to await from there ... and await from there ... until you finally call something that is not your code. If you can await that code that is not yours, then you are set. If you cannot, then you should not use async await form the very beginning.
(no way this made sense)