I have questions regarding the execution order of async jobs.
I will ask my question with example because it is easier to be understandable.
It is an official example from https://msdn.microsoft.com/en-us/library/mt674882.aspx with some twist.
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
//async operation:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoWork1();
// The await operator suspends AccessTheWebAsync.
string urlContents = await getStringTask;
DoWork2();
return urlContents.Length;
}
Can I say DoWork2
is a callback of client.GetStringAsync
?
If so, DoWork2
is not immediately executed following the completion of client.GetStringAsync
IF DoWork1
runs longer time than client.GetStringAsync
.
Am I right here?
The await keyword is used in an async function to ensure that all promises returned in the async function are synchronized, ie. they wait for each other. Await eliminates the use of callbacks in . then() and .
Callbacks. An event handler is a particular type of callback. A callback is just a function that's passed into another function, with the expectation that the callback will be called at the appropriate time. As we just saw, callbacks used to be the main way asynchronous functions were implemented in JavaScript.
Callback, Promises, and Async-await are a way to deal with asynchronous data. Asynchronous programming in JavaScript is a way in which the program doesn't wait until the execution of something is going on. This comes in handy when we do an API call to fetch some data, which takes some time (maybe 2–3 sec).
Async functions not only allow the programmer to escape from callback hell and promise chaining in asynchronous code, but they also make the code seemingly synchronous.
DoWork2
is not immediately executed following the completion ofclient.GetStringAsync
ifDoWork1
runs longer time thanclient.GetStringAsync
Once you hit that point await client.GetStrinkAsync
, DoWork1()
has already completed, as from your example it looks as it's execution is synchronous. Once client.GetStringAsync
completes, then DoWork2
is set to execute.
The execution flow will be:
GetStringAsync
asynchronously starts. It is executed until it hits it's first internal await
, and then yields control back to AccessTheWebAsync
.DoWork1()
kicks off. As it's synchronous, everyone waits for it's completionclient.GetStringAsync
is asynchronously waited for completion. await
will naturally yield the control of execution to it's caller.client.GetStringAsync
completes, execution will return to AccessTheWebAsync
and DoWork2()
will execute synchronously.urlContents.length
will be returned.Generally, everything after the first await
keyword is set to be the continuation for the rest of the method.
Yuval's answer is correct.
To answer your followup question:
Is there a way to make the DoWork2 immediately executed once client.GetStringAsync is finished?
Possibly. It depends on the context of this code. It's not possible to have DoWork1
and DoWork2
both running on the UI thread at the same time (obviously, a single thread can only do one thing at a time). But if this is called from a thread pool context, then sure, it's possible to run them both simultaneously.
However, you should shift your thinking from "callback" to "operation". That is, don't think of it as DoWork2
being a "callback" of GetStringAsync
. Instead, think of it like this: I have an operation GetStringAsync
, and I have an operation DoWork2
; I need a new operation that does one and then the other.
Once you shift your thinking this way, the solution is to write a method for the new operation:
async Task<string> GetStringAndDoWork2Async()
{
HttpClient client = new HttpClient();
var result = await client.GetStringAsync("http://msdn.microsoft.com");
DoWork2();
return result;
}
Now you can use that new operation in your higher-level method:
async Task<int> AccessTheWebAsync()
{
var task = GetStringAndDoWork2Async();
DoWork1();
string urlContents = await task;
return urlContents.Length;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With