为什么此异步/等待代码不会导致死锁? [英] Why does this async/await code NOT cause a deadlock?

查看:85
本文介绍了为什么此异步/等待代码不会导致死锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在乔恩·斯基特(Jon Skeet)的"C#深入.第三版"中找到了以下示例:

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:

  1. Main方法在主线程中同步调用GetPageLengthAsync.
  2. GetPageLengthAsync发出异步请求,并立即将Task<int>返回到Main,并说等待一会儿,我将在一秒钟内将您返回一个int值".
  3. Main继续执行并偶然发现lengthTask.Result,这导致主线程阻塞并等待lengthTask完成其工作.
  4. GetStringAsync完成并等待主线程变得可用以执行Length并开始继续.
  1. Main method calls GetPageLengthAsync synchronously within the main thread.
  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".
  3. Main continues execution and stumbles upon lengthTask.Result which causes the main thread to block and wait for lengthTask to finish its work.
  4. GetStringAsync completes and waits for main thread to become available to execute Length and start continuation.

但是似乎我误会了一些东西.为什么此代码不会死锁?

But it seems like I misunderstand something. Why doesn't this code deadlock?

此StackOverflow有关await/async死锁的问题中的代码似乎做同样的事情,但是却陷入僵局.

The code in this StackOverflow question about await/async deadlock seems to do the same, but deadlocks.

推荐答案

await返回原始同步上下文,无论是UI线程(在桌面UI应用程序中)还是ASP.NET中的请求上下文(不是核心) ).

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).

在GUI应用程序中,由于UI线程已被.Result锁定,因此将出现死锁. await将永远等待此呼叫结束.

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.

控制台应用程序和ASP.NET Core没有同步上下文,因此调用.Result不会导致死锁.

Console applications and ASP.NET Core have no synchronization context, so calling .Result won't cause a deadlock.

VS 15.3的PS:

Visual Studio 2017 15.3预览版2 (gasp )允许异步主应用程序.有了它,您可以编写:

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);
}

这篇关于为什么此异步/等待代码不会导致死锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆