Consider an asynchronous (*Async / async) function that is called twice, one time with await and other without it.
If I use await, will it wait until the asynchronous function is executed and then execute the next line?
await db.SaveChangesAsync();
//Some code here
And, if I don't use await, will it continue with executing the code below it without waiting for the asynchronous function to complete?
db.SaveChangesAsync();
//Some code here
Am, I right over here or await is mandatory when it comes to async functions?
If I use await, will it wait till the async function is executed and then execute the next line.
That depends on the method returns. It returns a Task[<T>], which represents a future value. If the Task is already completed, it keeps running synchronously. Otherwise, the remaining portion of the current method is added as a continuation - a delegate callback that is invoked when the asynchronous portion reports completion.
What it does not do, in either case, is block the calling thread while the asynchronous part continues.
And, if I don't use await, will it continue with executing the code below it without waiting for the async function to complete.
Yes
...or await is mandatory when it comes to async functions?
When invoking them? Not mandatory, but it does make things convenient. Usually, such functions return a Task[<T>], which can also be consumed via different code. You could use .ContinueWith(...), .Wait, .Result, etc. Or you could just ignore the Task completely. The last is a bad idea, because exceptions on asynchronous functions need to go somewhere: very bad things happen if exceptions are not observed.
When writing them, however: if you write an async method and don't have an await keyword in there, the compiler will present a warning indicating that you're probably doing something wrong. Again, not strictly mandatory, but highly recommended.
Related
This question already has answers here:
When does 'await' immediately leave a method and when does it not?
(6 answers)
Closed 9 months ago.
After reading a lot about async/await I still have a fundamental question (that I kind of assume the answer but I just want confirmation).
Let's discuss over some code:
async Task methodA() {
//code A (without awaits or Task.Run)
Task.Run(()=> //code A' (without awaits or Task.Run))
}
async Task methodB() {
//code B (without awaits or Task.Run)
await methodA();
}
void Main() {
//code C (without awaits or Task.Run)
methodB(); (no await)
//code D (without awaits or Task.Run, no pun intended)
}
What I think will happen:
Run code C
Run code B
Run code A
Run code A' and code D (different threads, in parallel)
The doubt comes from what's in the documentation:
The await operator suspends evaluation of the enclosing async method
until the asynchronous operation represented by its operand completes. [...]
The await operator doesn't block the thread that evaluates the async method.
The key being here what represents an asynchronous operation. Cause considering this other piece of documentation:
The await operator tells the compiler that the async method can't
continue past that point until the awaited asynchronous process is
complete. In the meantime, control returns to the caller of the async
method.
One might think that, since methodA() is async, once methodB reaches the await methodA(), then it might return control to the caller and allow to run code D in parallel to code A and code A'.
The essence is if method A constitutes an asynchronous operation as described in the documentation, or only until it reaches truly async code (code that runs on another thread) then it actually allows control to return to the caller (which in this case is code A').
My understanding is that asynchronous operation is an operation that will run on another thread, is this correct? So things like Task.Run, Task.Delay, Task.Sleep..? And that even though code A is within an async method, it is not an async operation and control does not go immediately back when awaiting methodA. Is this correct?
Just for completion, check this question where in the answer's comments they argue precisely about this, without a very clear answer.
[...], control returns to the caller of the async method.
This sentence had confused the hell out of me when I was learning asynchronous programming. What it means is that the Task is created and returned. You can think the asynchronous methods as generators for Task objects. The async method has to do some work in order to create the Task. This work completes when the first await of an incomplete awaitable inside the method is reached. At that point the Task is created, it is handed to the caller of the method, and the caller can do whatever it wants with it.
Usually the caller awaits the task, but it can also do other things before awaiting it, or it might never await it and completely ignore it, although this is not recommended. Generally you want to keep track of your tasks, and not let them run unattended in a fire-and-forget fashion.
When the caller does not await immediately the returned task, and the task was not in a completed state upon creation, you introduce concurrency in your application: More than one things might be happening at overlapping time spans. You can read about the differences between concurrency and parallelism here.
I have an async method that get data from a database:
private async Task getDataAsync()
{
await getDataFromDatabaseAsync();
}
I have a contructor that uses this method, in this way:
public MyViewModel()
{
Task.WhenAll(getDataAsync());
//getDataAsync().ConfigureAwait(false);
//next line of code
}
The only way that I get to avoid the applications isn't blocked is using one the two options, both seems to work fine. I can use WhenAll or I can use ConfigureAwait(false).
Another options it is calling the method getDataASync() inside a task, but I guess it is a worse option becase it takes more resources.
So I would like to know which is the differences between WhenAll and ConfigureAwait.
When I use WhenAll in this way, the line of code "next line of code" is run after the async method is finisihed or it will run before finish?
Thanks.
There is a common misconception that when you make a method async, it will be actually executed asynchronously (i.e. on a separate thread). That is not the case: async and await are a means to synchronize already asnychronous code. If you have nothing that is executed on a separate thread, your async code will run fully synchronously to the end.
Since getDataAsync is executed on the same thread as the MyViewModel constructor, you can run into a deadlock, since the thread waits for itself. When you use ConfigureAwait, you can avoid this situation.
Whether you actually should do that is a different question. What you are actually doing with ConfigureAwait is to start the task and to allow the await to continue on a separate context (which can be on a separate thread). Apart from the fact that you are not even using await here, continuation in a different context can become a problem when you want to execute UI operations after the await.
If you want to be sure that you can wait for getDataAsync in your constructor, you can use Task.Run to force execution in the thread pool:
var getDataTask = Task.Run((Func<Task>)getDataAsync);
//Do something else
getDataTask.Wait();
Everything you execute between Task.Run and the Wait() can run during the execution of getDataAsync. Whether parallelism is actually worth it here depends on what else you do until the Wait().
What you are doing in the MyViewModel constructor is to finally synchronize all asynchronous operations and make the execution of the constructor synchronous. If you want to run that operation asynchronously, you would need to start another task to do it. So you should be really sure that beyond that point async is not required anymore. If it is, run the initialization on another async method, await getDataAsync() there and synchronize somewhere up the call chain.
I'm currently getting into the async/await keywords, and went through the following questions: When correctly use Task.Run and when just async-await and Async/Await vs Threads
However even the second link doesn't answer my question, which is when to simply use
Task.Run(...)
versus
await Task.Run(...)
Is it situational or is there something to be gained by using await (and thus returning to the caller)?
The code Task.Run(...) (in both examples) sends a delegate to the thread pool and returns a task that will contain the results of that delegate. These "results" can be an actual return value, or it can be an exception. You can use the returned task to detect when the results are available (i.e., when the delegate has completed).
So, you should make use of the Task if any of the following are true:
You need to detect when the operation completed and respond in some way.
You need to know if the operation completed successfully.
You need to handle exceptions from the operation.
You need to do something with the return value of the operation.
If your calling code needs to do any of those, then use await:
await Task.Run(...);
With long-running background tasks, sometimes you want to do those (e.g., detect exceptions), but you don't want to do it right away; in this case, just save the Task and then await it at some other point in your application:
this.myBackgroundTask = Task.Run(...);
If you don't need any of the above, then you can do a "fire and forget", as such:
var _ = Task.Run(...); // or just "Task.Run(...);"
Note that true "fire and forget" applications are extremely rare. It's literally saying "run this code, but I don't care whether it completes, when it completes, or whether it was successful".
You can use Task.Run() when handling logic with fire and forget type, similar to invoking events if someone is subscribed to them. You can use this for logging, notifying, etc.
If you depend of the result or actions executed in your method, you need to use await Task.Run() as it pauses current execution until your task is finished.
I am just new to this world of asynchronous stuff.
Please bear with my lack of knowledge.
It is said when a method encounters await ... "It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method."
I did not get this part.
So does it mean the method still keeps on running synchronously and waits till the awaitable returns and then proceeds with the rest of the method?
If not please explain then why Task.Run is needed to run a method in the background or in a fire and forget manner. I could still be achieved via await also right? i.e.
The method keeps on executing the rest of the statements without waiting for the await to return.
I hope that is similar to a background run approach. Or is not it? I am confused.
If a method is marked with async and await and that in turn calls another method asynchronously in a separate layer that's also marked with async and await ..
then how the the call of the first method that's marked with async and await from a separate method say name ABC should look like?
I do not want to annotate that method to be async/await. So
Task.Run(() => DoWork());
from ABC () is fine without marking it async/await?
Or is it against the principle of asynchrony?
Here is what I am trying to achieve ...
public IList<CreateCaseOutput> ABC(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)
{
CaseSQL.getABCParameters(CreateCaseInput, RequestType, out strSPQuery, out listParam);
var AcctLst = rep.ExecuteStoredProcedure<CreateCaseOutput>(strSPQuery, listParam).ToList();
if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString()))
{
Task.Run(async () =>
{
await DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
}).ConfigureAwait(false);
}
console.writeLine("After Async called");
return AcctLst;
}
public async Task<SaveCaseSearchOutput>> DEF(SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key)
{
CaseSQL.getDEFParameters(SaveCaseSearchInput, case_key, out strSPQuery, out listParam);
var AcctLst = await rep.ExecuteStoredProcedureAsync<SaveCaseSearchOutput>(strSPQuery, listParam);
return AcctLst;
}
DEF which is async/await needs to be called in the background in fire and forget approach from ABC and once fired I want to continue with rest of ABC and run DEF in the background. What's wrong in this fire and forget approach ? If I call
only
DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
instead of
Task.Run(async () =>
{
await DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
}).ConfigureAwait(false);
}
return AcctLst;
then this code runs synchronously in debugger.
Am I doing something wrong ?
So does it mean the method still keeps on running synchronously and waits till the awaitable returns and then proceeds with the rest of the method?
No. The awaitable has a "callback" mechanism. So, the method just registers itself with the awaitable. When the awaitable completes, it will execute its callbacks, which include the continuation of the async method.
In the meantime, the async method returns an incomplete task.
If not please explain then why Task.Run is needed to run a method in the background or in a fire and forget manner.
If you want to run on a background thread, then use Task.Run. Task.Run just schedules work to the thread pool.
I could still be achieved via await also right? i.e.
The method keeps on executing the rest of the statements without waiting for the await to return.
I hope that is similar to a background run approach. Or is not it? I am confused.
Well, you could "forget" the task by just not awaiting it:
MyMethod()
{
SomeMethodAsync(); // Note: no await; we just ignore the task.
}
You almost never want to do "fire and forget", though. Easily >90% of the time people ask for it, it's actually a design error.
I do not want to annotate that method to be async/await... Or is it against the principle of asynchrony?
That's against the principle. If you think about it, it doesn't really make sense to block on asynchronous code. You want to go through the trouble of making a method asynchronous (meaning it doesn't block a thread), and then block a thread on it? Why, exactly? Sometimes in practice, the code will temporarily end up in this kind of state during a transition to asynchronous code, but it's a tricky place to be.
For more information, see my article on async best practices, particularly "async all the way".
'It is said when a method encounters await ... "It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method."'
So let's say you have a method A that calls a method B. Method B has the "async" keyword in its declaration. In method B there is a time-consuming call to LongMethod, which ultimately returns a string.
What we want here is for method A to not have to wait for ages for method B's LongMethod to complete. So we write in Method B:
string newVariable = await Task.Run(()=>LongMethod());
If LongMethod itself is also async, then LongMethod can only return a void, a non generic Task or a generic Task. Therefore we would have to change the return type in the LongMethod declaration to Task<string>
So back to our story, the LongMethod task has started... At this point method A resumes from the next line of code after the call to method B, and method B continues to wait for the LongMethod to finish, so there are now two threads running. Eventually, the LongMethod completes and method B runs to the end, meanwhile method A has continued to run, or has maybe even finished running.
I hope this gives you a picture of the relationship between Async/Await and Tasks.
Now for question 2:
I think your question is basically asking if Method A in my example needs to be marked "async" because it makes a call to a method marked "async", and no it does not. Also please note that ABC() just needs to have
DoWork()
Not
Task.Run(() => DoWork());
ABC will then stop running until the DoWork method arrives at an 'await' statement.
If DoWork just needs to be run as its own task, and you don't want ABC() to stop at all, then just do
Task.Run(() => DoWork());
There is no benefit marking DoWork as async in this case, because there is no point having any await statements in DoWork.
I hope this helps, sorry if I've misinterpreted your questions!
From what you said in your comment (I'll assume you need the result in ABC)
You just need to write
Task<SaveCaseSearchOutput> t = Task.Run(() =>DEF(SaveCaseSearchInput,AcctLst.ElementAt(0).o_case_seq));
in ABC, instead of the current Task.Run call.
Then at the line in ABC when you require the result write
t.Wait();
SaveCaseSearchOutput g = t.Result;
DEF must remain async but you can remove the await statement in DEF.
When we use await in the code, generally the awaiters capture the context and use that as callback when the awaited task completed successfully. But, since await is generally a No-Op (No Operation), does it make the underlying thread not being reusable until execution of the awaited task completes?
For Example:
public async Task MethodAAsync()
{
// Execute some logic
var test = await MethodB();
// Execute remaining logic
}
Here, since I need the result back to proceed further, I need to await on that. But, since we are awaiting, does it block the underlying thread resulting thread not being used to execute any tasks?
But, since await is generally a No.Op(No Operation), does it make the
underlying thread not being reusable until execution of awaited task
completes?
I'm not sure where you got this information from, but await is certainly not a No-Op. Calling await on a Task, for example, will invoke a logical call to Task.GetAwaiter, where the TaskAwaiter has to implement INotifyCompletion or ICriticalNotifyCompletion interface, which tells the compiler how to invoke the continuation (everything after the first await).
The complete structure of async-await transforms your call to a state-machine such that when the state-machine hits the first await, it will first check to see if the called method completed, and if not will register the continuation and return from that method call. Later, once that method completes, it will re-enter the state-machine in order to complete the method. And that is logically how you see the line after await being hit.
But, since we are awaiting, does it block the underlying thread
resulting thread not being used to execute any tasks?
No, creating an entire mechanism only to block the calling thread would be useless. async-await allow you to actually yield the calling thread back to the caller which allows him to continue execution on that same thread, while the runtime takes care of queuing and invoking the completion.
In short, no, it doesn't block your thread.
More info: http://blog.stephencleary.com/2013/11/there-is-no-thread.html
The thread has a local queue of Tasks. Once it hits an await it will pick up another Task from it's queue (assuming all methods up it's stack are awaited). If the queue is empty, it will try to get a Task from the global queue, and if it's empty too - the thread will try to get a Task from another thread's own local queue. In a simple program, where all threads might get "out of Tasks" - the thread will remain idle until one of the Tasks returns.