[英]Why does this async/await code NOT cause a deadlock?
I have found the following example in Jon Skeet's "C# in depth. 3rd edition":我在 Jon Skeet 的“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 calls GetPageLengthAsync
synchronously within the main thread. Main
方法在主线程内同步调用GetPageLengthAsync
。GetPageLengthAsync
makes an asynchronous request and immediately returns Task<int>
to Main
saying "wait for a while, I will return you an int in a second". GetPageLengthAsync
发出一个异步请求,并立即将Task<int>
返回给Main
说“稍等片刻,我将在一秒钟内返回一个 int”。Main
continues execution and stumbles upon lengthTask.Result
which causes the main thread to block and wait for lengthTask
to finish its work. Main
继续执行并偶然发现lengthTask.Result
导致主线程阻塞并等待lengthTask
完成其工作。GetStringAsync
completes and waits for main thread to become available to execute Length
and start continuation. GetStringAsync
完成并等待主线程变得可用于执行Length
并开始继续。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. 这个 StackOverflow 问题中关于 await/async 死锁的代码似乎做了同样的事情,但是死锁。
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). await
返回到原始同步上下文,无论是 UI 线程(在桌面 UI 应用程序中)还是 ASP.NET 中的请求上下文(不是核心)。
In a GUI application, you'd have a deadlock because the UI thread was locked by .Result
.在 GUI 应用程序中,您会遇到死锁,因为 UI 线程被.Result
锁定。 await
would await forever for this call to finish. await
将永远等待此调用完成。
Console applications and ASP.NET Core have no synchronization context, so calling .Result
won't cause a deadlock.控制台应用程序和 ASP.NET Core 没有同步上下文,因此调用.Result
不会导致死锁。
PS for VS 15.3: VS 15.3 的 PS:
Visual Studio 2017 15.3 Preview 2 (gasp) allows asynchronous main applications. Visual Studio 2017 15.3 Preview 2 (gasp) 允许异步主应用程序。 With it, You can write :有了它,你可以写:
public static Task Main()
{
var length = await GetPageLengthAsync("http://csharpindepth.com");
Console.WriteLine(length);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.