问题
I have found the following example in Jon Skeet's "C# in depth. 3rd edition":
static async Task<int> GetPageLengthAsync(string url)
{
using (HttpClient client = new HttpClient())
{
Task<string> fetchTextTask = client.GetStringAsync(url);
int length = (await fetchTextTask).Length;
return length;
}
}
public static void Main()
{
Task<int> lengthTask = GetPageLengthAsync("http://csharpindepth.com");
Console.WriteLine(lengthTask.Result);
}
I expected that this code would deadlock, but it does not.
As I see it, it works this way:
Main
method callsGetPageLengthAsync
synchronously within the main thread.GetPageLengthAsync
makes an asynchronous request and immediately returnsTask<int>
toMain
saying "wait for a while, I will return you an int in a second".Main
continues execution and stumbles uponlengthTask.Result
which causes the main thread to block and wait forlengthTask
to finish its work.GetStringAsync
completes and waits for main thread to become available to executeLength
and start continuation.
But it seems like I misunderstand something. Why doesn't this code deadlock?
The code in this StackOverflow question about await/async deadlock seems to do the same, but deadlocks.
回答1:
await
returns to the original synchronization context, whether that is the UI thread (in desktop UI applications) or the request context in ASP.NET (not core).
In a GUI application, you'd have a deadlock because the UI thread was locked by .Result
. await
would await forever for this call to finish.
Console applications and ASP.NET Core have no synchronization context, so calling .Result
won't cause a deadlock.
PS for VS 15.3:
Visual Studio 2017 15.3 Preview 2 (gasp) allows asynchronous main applications. With it, You can write :
public static Task Main()
{
var length = await GetPageLengthAsync("http://csharpindepth.com");
Console.WriteLine(length);
}
来源:https://stackoverflow.com/questions/44544053/why-does-this-async-await-code-not-cause-a-deadlock