I am new to async/await and I can not wrap my head around the thread creation.
My queries are:-
- Does async function without await creates a new thread to cater getData() as Main thread will not be blocked?
- What is Task as a return type doing here? Does it help with any thread creation?
- The result of this code is 1,2,ended,3 (Why is 2 printed before ended?)
Here is my code:
public class Class1
{
public async Task getValue()
{
Console.WriteLine("1");
var str = getData();
Console.WriteLine("ended");
Console.ReadKey();
}
private async Task<string> getData()
{
Console.WriteLine("2");
for (long i = 0; i < 100000000000000; i++)
{
continue;
}
Console.WriteLine("3");
return "ss";
}
}
Some forums said that Task is responsible for State management only and no new threads are being created.
But those questions are still in my head.
Please help
2
Answers
Marking method as
async
does not actually makes it magically asynchronous, it still is a synchronous one unless it does something "truly async" (usually it is an awaited call to another "truly async" method). Everything before firstawait
on "truly async" call will be executed synchronously.Since your method is not actually an async one it will block current thread until it is completed. If you want to return control to the calling method you can add call like
await Task.Delay(...)
:Which should result in the expected behavior (i.e.
2
printed afterended
).No, it does not.
It allows caller to
await
thegetData
call when needed.Task
is basically a future/promise which represents a result of some computation which can finish in the future.I highly recommend to read about the topic more:
According to Microsoft’s guidelines:
Your
getData
asynchronous method violates this guideline by doing all the work synchronously, and returning a completed task. This can be easily verified:And most likely also:
Some people would disagree that is OK to call the
getData
"asynchronous". They would call it synchronous, or fake asynchronous. The terminology that I prefer is that thegetData
is a method with asynchronous signature and synchronous implementation. To answer your questions directly:No, a new thread in not created. All code runs on the main thread of the console application.
The
Task
represents the completion of the asynchronous method. In case an exception is thrown inside theasync
method, the information about the exception will be stored inside thisTask
. Invoking thegetData
will never throw synchronously the exception. In order to expose the exception, you’ll have toWait
orawait
the resultingTask
. TheTask
doesn’t create any thread by itself, no.Because all code runs synchronously on the same thread from start to finish.
The purpose of the
async
/await
technology is to enable the composition of derived asynchronous methods that are based on primitive asynchronous methods. For example if you have a built-in asynchronous API like theHttpClient.GetStringAsync
, you can easily use it to author an asynchronous method that fetches some information from the internet based on specific parameters, and returns a deserialized representation of the data. The data will be returned on a thread that is decided by the implementation of the primitive API that you are calling. When theTask
completes, theawait
continuation will run on whatever thread was selected by theHttpClient.GetStringAsync
implementation. It’s not up to you to decide. What the caller of your API can do is to install a specializedSynchronizationContext
on the current thread, that will cause a redirection from the thread selected by theHttpClient.GetStringAsync
implementation to a thread selected by theSynchronizationContext
implementation. Most UI frameworks (WinForms, WPF etc) install automatically their own specializedSynchronizationContext
on the UI thread, so the developers don’t have to do anything special. You can learn more about this here:await
keyword?