简体   繁体   English

为什么这个异步/等待代码不会导致死锁?

[英]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:在我看来,它是这样工作的:

  1. Main method calls GetPageLengthAsync synchronously within the main thread. Main方法在主线程内同步调用GetPageLengthAsync
  2. 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”。
  3. 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完成其工作。
  4. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM