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.
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 run these two versions and it seems like each is giving me the same output, which is sequential.
ContinueWith_Method1a();
ContinueWith_Method1b();
and
Task.Run(() => ContinueWith_Method1a())
.ContinueWith(task => ContinueWith_Method1b())
.Wait();
I tried with the below but get this error:
Cannot implicitly convert type 'void' to 'System.Threading.Tasks.Task'
Task t = Task.Run(() => ContinueWith_Method1a())
.ContinueWith(task => ContinueWith_Method1b())
.Wait();
static void ContinueWith_Method1a()
{
System.Console.WriteLine("Continue With Method 1a started.");
Thread.Sleep(1000);// Simulate task processing time.
System.Console.WriteLine("Continue With Method 1a completed.");
}
static void ContinueWith_Method1b()
{
System.Console.WriteLine("Continue With Method 1b started.");
Thread.Sleep(1000);// Simulate task processing time.
System.Console.WriteLine("Continue With Method 1b completed.");
}
ContinueWith starts the next Task after the first finished.
So both your examples run synchroniously ( first methode A then methode b)
EDIT:
As an addition to your edit, your error is caused by the .Wait() function, which awaits the Task and returns void.
What's the difference with ContinueWith and without?
The title question of your post is very misleading. The use of ContinueWith() in your code examples is the least interesting difference. The much more significant difference is that the first example just calls the methods directly, while the second uses Task.Run().
Now, as it happens there would be no reason to write the code as in your second example. Even ignoring the ContinueWith() aspect, if all your task does is call a method, and all you're going to do with the task is synchronously wait on the task (i.e. call the Wait() method), then you might as well just call that method in your current thread. No need for Task.Run() in that situation.
Similarly, if all you're going to do with ContinueWith() is call another method immediately after, you might as well just call the method directly.
By blocking in the current thread, you've rendered useless any advantage there might have been in executing those two methods asynchronously.
Of course, there is a clear mechanical difference. You get the same results, ultimately, but how that result is achieved is very different. In the first example, you just call the methods, one after another. Each call executes in the current thread. In the second example, you are essentially asking the thread pool to execute each method in sequence, while you block the current thread waiting for that to happen.
It's similar to the difference between you peeling an onion and then chopping it yourself, and asking someone else to peel an onion and then chop it while you sit around twiddling your thumbs waiting for them to finish those actions.
Finally, as far as the error message you got, "Cannot implicitly convert type 'void' to 'System.Threading.Tasks.Task'", that only happened because you added the Task t variable and tried to set it to the result of the Wait() method. Since the Wait() method doesn't return anything (i.e. has a declared return type of void), never mind a value of Task, it's not possible to set the value of t using its return value. Hence the error message. If you want to assign a Task variable, you would need to just leave out the call to Wait():
Task t = Task.Run(() => ContinueWith_Method1a())
.ContinueWith(task => ContinueWith_Method1b());
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 have three methods where the first result will be used in the next two methods and no data expected to be return back.
result= await DataAccess.Query(param); //Query
await DataAccess.Create(result);
await DataAccess.Update(result);
Do I really need to use await here?
is it correct to use async void
in create and update function?
what will be the right approach to do
a fire and forget here?
if Im not mentioning async will it be fire
and forget?
what is the significance of async without await if it
only used to run synchronously? I can even achieve that without that keyword.
no data expected to be return back.
What about errors? Do you need to return an error code if an error occurs, or is 200 OK acceptable even if the Create or Update fails?
I'm assuming you'll need an error code. 99.99% of calls do.
Do I really need to use await here?
Well, if you want synchronous methods, then you can just call synchronous APIs. I don't know why you would want that, though.
As a reminder: await has nothing to do with returning to the browser. It has everything to do with using fewer thread pool threads, allowing your server to scale further.
is it correct to use async void in create and update function?
No. Never.
what will be the right approach to do a fire and forget here?
The correct approach is "don't". Fire-and-forget is difficult to do correctly, and in fact since you need an error code, you can't do fire-and-forget.
I write more about fire-and-forget - including why StartNew and Task.Run are invalid solutions - on my blog. Note that the only fully reliable solution (including upgrade scenarios) is the last one (distributed architecture).
what is the significance of async without await if it only used to run synchronously? I can even achieve that without that keyword.
It's running serially (in order), not synchronously (blocking a thread). The benefit of async is to allow greater scalability. For more information, see my intro to async on ASP.NET article.
If you need to call several methods in specific order, but this whole set of functions can run asynchronously, I would do:
Task.Run(() =>
{
result = Function();
Create(result);
Update(result);
});
This will separate group of functions into new thread. Since you are not awaiting this task, it is fire and forget.
If your functions are defined as async, you can wait for them to finish like this:
Task.Run(() =>
{
var task = Function();
task.Wait();
var result = task.Result;
Create(result).Wait();
Update(result).Wait();
});
But when you are not going to benefit from async methods, it will be better to override your methods to run synchronously and use the first code
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.