我发现在乔恩斯基特的下面的例子“C#深入第三版”:为什么这个异步/等待代码不会导致死锁?
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
@Jodrell这是GUI/ASP.NET应用程序中的一个常见问题 - .Result阻塞了UI线程,所以'await'无法返回到原始同步上下文。相同的ASP.NET。控制台和.NET Core应用程序(包括ASP.NET Core)没有同步上下文 –
@juharr OP询问了一个有效的问题。如果您在WinForms,WPF或ASP.NET应用程序 –