I have been reading about c# async methods in the past 2 days and from what I understand, unlike in a thread (threadpool.queueuserworkitem())
, a call to an async method does not return immediately and it only returns when the called method hits an await or complete(or exception)
Please see the following example.
public partial class MainWindow : Window
{
// . . .
private async void startButton_Click(object sender, RoutedEventArgs e)
{
// ONE
Task<int> getLengthTask = AccessTheWebAsync();
// FOUR
int contentLength = await getLengthTask;
// SIX
resultsTextBox.Text +=
String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
}
async Task<int> AccessTheWebAsync()
{
// TWO
HttpClient client = new HttpClient();
Task<string> getStringTask =
client.GetStringAsync("http://msdn.microsoft.com");
// THREE
string urlContents = await getStringTask;
// FIVE
return urlContents.Length;
}
}
From what I gather, in the above code, AccessTheWebAsync()
is called synchronously(i.e. control does not return immediately when it is called). But in the line named 'THREE', the runtime will return control.
My questions are:
How does the runtime decide when to use the threadpool or when to run the task in the calling thread? (i.e. execute the code without returning control)
At which points in the above code, new threads (or thread pool) will be used?
If AccessTheWebAsync()
did something computationally intensive, like running a loop with a zillion iterations, the control will only return to the caller when the loop is completed. Is that right?
In an async function, is there a way to return the control immediately and then continue doing the work in say a background thread? (just like if we called threadpool.queueuserworkitem())
Is calling an async method without an await in it (assume it s possible) same as calling a non async method?
First something important: The runtime will only return to the caller on await
if the task to await hasn't completed yet.
Question 1: I'll quote the MSDN here:
The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread.
Source
Question 2: Maybe in the implementation of GetStringAsync
but we don't know that and we also don't have to know it. It's enough for us to know that GetStringAsync
somehow gets its result without blocking our thread.
Question 3: If the loop is placed before the await
keyword, yes.
Question 4: Quote from the same paragraph as before:
You can use Task.Run to move CPU-bound work to a background thread
You don't need the async
and await
keywords for this. Example:
private Task<int> DoSomethingAsync()
{
return Task.Run(() =>
{
// Do CPU heavy calculation here. It will be executed in the thread pool.
return 1 + 1;
});
}
Question 5: I'll quote again
An async method typically contains one or more occurrences of an await operator, but the absence of await expressions doesn’t cause a compiler error. 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.
Source (same page as before, just a different section)
How does the runtime decide when to use the threadpool or when to run the task in the calling thread?
If there is a synchronization context and you don't explicitly specify you don't want to continue on the context (by using something like await task.ConfigureAwait(false)
), then the method will resume on the captured context. In UI applications, that context is the UI thread, assuming the method is called from the UI thread.
At which points in the above code, new threads (or thread pool) will be used?
Nowhere. Unless you specify otherwise (see above), await
resumes back on the captured context, which in your case is the UI thread.
If
AccessTheWebAsync()
did something computationally intensive, like running a loop with a zillion iterations, the control will only return to the caller when the loop is completed. Is that right?
Yes, assuming the loop was before the first “asynchronous” await
. (await
can also be “synchronous” if the await
ed Task
is already completed.)
In an async function, is there a way to return the control immediately and then continue doing the work in say a background thread?
You should use Task.Run()
for that.
Is calling an async method without an await in it (assume it s possible) same as calling a non async method?
It is possible and the compiler will warn you that the method will execute completely synchronously.
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