Async - await
-
Hi, Why Sample #2 is "Bets Practices". Second sample include "await" keyword on the same line with Async Method. Both codes are blocking Thread. Any idea? thanks... Sample #1
var products = _context.Products.ToList();
Sample #2
var products = await _context.Products.ToListAsync();
-
Hi, Why Sample #2 is "Bets Practices". Second sample include "await" keyword on the same line with Async Method. Both codes are blocking Thread. Any idea? thanks... Sample #1
var products = _context.Products.ToList();
Sample #2
var products = await _context.Products.ToListAsync();
It gets a complicated, but basically the
await
call spins off a second thread to execute the long running task, and effectively suspends the method until it's complete. But ... the thread that executedawait
can continue as if the method had finished. This is handy if you want to run a long task from the main (UI) thread while the UI remains responsive. For example, if you run this code:private void MyOtherButton\_Click(object sender, EventArgs e) { Debug.WriteLine("Before Sleep"); Thread.Sleep(10000); Debug.WriteLine("After Sleep"); }
Your console will print "Before Sleep", wait ten seconds and print "After Sleep" - but your user can't do anything else with your app in the mean time. But this code:
private async void MyOtherButton\_Click(object sender, EventArgs e) { Debug.WriteLine("Before Sleep"); await Task.Run(() => Thread.Sleep(10000)); Debug.WriteLine("After Sleep"); }
Prints the same things, but your user can carry on working - your UI remains working. Have a look here: https://www.pluralsight.com/guides/understand-control-flow-async-await[^] - it explains it pretty well, and shows examples.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
-
It gets a complicated, but basically the
await
call spins off a second thread to execute the long running task, and effectively suspends the method until it's complete. But ... the thread that executedawait
can continue as if the method had finished. This is handy if you want to run a long task from the main (UI) thread while the UI remains responsive. For example, if you run this code:private void MyOtherButton\_Click(object sender, EventArgs e) { Debug.WriteLine("Before Sleep"); Thread.Sleep(10000); Debug.WriteLine("After Sleep"); }
Your console will print "Before Sleep", wait ten seconds and print "After Sleep" - but your user can't do anything else with your app in the mean time. But this code:
private async void MyOtherButton\_Click(object sender, EventArgs e) { Debug.WriteLine("Before Sleep"); await Task.Run(() => Thread.Sleep(10000)); Debug.WriteLine("After Sleep"); }
Prints the same things, but your user can carry on working - your UI remains working. Have a look here: https://www.pluralsight.com/guides/understand-control-flow-async-await[^] - it explains it pretty well, and shows examples.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
OriginalGriff wrote:
the await call spins off a second thread to execute the long running task
A common misconception. :)
await
is almost nothing to do with multi-threading; it's more about using IO-completion ports to avoid keeping a thread spinning whilst it waits for an external resource to respond.OriginalGriff wrote:
private async void MyOtherButton_Click(object sender, EventArgs e)
{
Debug.WriteLine("Before Sleep");
await Task.Run(() => Thread.Sleep(10000));
Debug.WriteLine("After Sleep");
}Aside from the fact that you should avoid
async void
wherever possible[^], spinning up a background thread just to make it sleep seems like a bad idea. :)private void MyOtherButton_Click(object sender, EventArgs e)
{
_ = MyOtherButton_Click_Async();
}private async Task MyOtherButton_Click_Async()
{
Debug.WriteLine("Before Sleep");
await Task.Delay(10000);
Debug.WriteLine("After Sleep");
}See David Fowler's explanation of the
_ = SomeTaskReturningMethod();
construct under the "Timer callbacks" heading: AspNetCoreDiagnosticScenarios/AsyncGuidance.md at master · davidfowl/AspNetCoreDiagnosticScenarios · GitHub[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
Hi, Why Sample #2 is "Bets Practices". Second sample include "await" keyword on the same line with Async Method. Both codes are blocking Thread. Any idea? thanks... Sample #1
var products = _context.Products.ToList();
Sample #2
var products = await _context.Products.ToListAsync();
The second code example doesn't block the thread; it blocks the rest of the method until the call has completed. The low-level thread is freed up to deal with other work until the
ToListAsync
call completes. Think of it like a car journey: in the first sample, your kids (the thread) spend the whole time yelling "Are we there yet? Are we there yet? Are we there yet?" until you reach your destination; with the second sample, they get on with reading a book quietly until you tell them you've arrived. One of those scenarios makes for a much nicer journey. ;)
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
The second code example doesn't block the thread; it blocks the rest of the method until the call has completed. The low-level thread is freed up to deal with other work until the
ToListAsync
call completes. Think of it like a car journey: in the first sample, your kids (the thread) spend the whole time yelling "Are we there yet? Are we there yet? Are we there yet?" until you reach your destination; with the second sample, they get on with reading a book quietly until you tell them you've arrived. One of those scenarios makes for a much nicer journey. ;)
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
A beautiful example, thank you for that.
I’ve given up trying to be calm. However, I am open to feeling slightly less agitated.
-
The second code example doesn't block the thread; it blocks the rest of the method until the call has completed. The low-level thread is freed up to deal with other work until the
ToListAsync
call completes. Think of it like a car journey: in the first sample, your kids (the thread) spend the whole time yelling "Are we there yet? Are we there yet? Are we there yet?" until you reach your destination; with the second sample, they get on with reading a book quietly until you tell them you've arrived. One of those scenarios makes for a much nicer journey. ;)
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
I got my answer, thanks. I have one more question. You said "it blocks the rest of the method" yes the following codes will not be executed until the job is complete, what exactly is waiting here? I guess it was a deep question :^)
-
I got my answer, thanks. I have one more question. You said "it blocks the rest of the method" yes the following codes will not be executed until the job is complete, what exactly is waiting here? I guess it was a deep question :^)
Behind the scenes, your
async
method will be rewritten into a state machine. Whenever youawait
something, so long as that operation doesn't complete immediately, the rest of your method will be signed up as a "continuation" to run when that asynchronous operation completes. As a simple example:public async Task Foo()
{
Console.WriteLine("Start...");
await Task.Delay(1000);
Console.WriteLine("Done.");
}would (logically) turn into something more like:
public Task Foo()
{
Console.WriteLine("Start...");
return Task.Delay(1000).ContinueWith(_ => Console.WriteLine("Done."));
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
Behind the scenes, your
async
method will be rewritten into a state machine. Whenever youawait
something, so long as that operation doesn't complete immediately, the rest of your method will be signed up as a "continuation" to run when that asynchronous operation completes. As a simple example:public async Task Foo()
{
Console.WriteLine("Start...");
await Task.Delay(1000);
Console.WriteLine("Done.");
}would (logically) turn into something more like:
public Task Foo()
{
Console.WriteLine("Start...");
return Task.Delay(1000).ContinueWith(_ => Console.WriteLine("Done."));
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Thank you very much for your interest and concern @RichardDeeming