【发布时间】:2017-11-16 13:31:18
【问题描述】:
我在 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);
}
我预计这段代码会死锁,但事实并非如此。
在我看来,它是这样工作的:
-
Main方法在主线程中同步调用GetPageLengthAsync。 -
GetPageLengthAsync发出一个异步请求并立即将Task<int>返回到Main说“等一下,我会在一秒钟内返回一个int”。 -
Main继续执行并偶然发现lengthTask.Result导致主线程阻塞并等待lengthTask完成其工作。 -
GetStringAsync完成并等待主线程可用以执行Length并开始继续。
但我好像误会了什么。为什么这段代码不会死锁?
this StackOverflow question about await/async deadlock 中的代码似乎也是如此,但出现了死锁。
【问题讨论】:
-
对于死锁,您需要两个异步活动竞争共享资源。我不明白你为什么认为这是这种情况。
-
@Jodrell 这是 GUI/ASP.NET 应用程序中的常见问题 - .Result 会阻塞 UI 线程,因此
await无法返回到原始同步上下文。对于 ASP.NET 也是如此。控制台和 .NET Core 应用程序,包括 ASP.NET Core 没有同步上下文 -
@juharr OP 提出了一个有效的问题。如果您在 WinForms、WPF 或 ASP.NET 应用程序中尝试此代码,您可能陷入死锁
标签: c# asynchronous async-await task-parallel-library