簡體   English   中英

為什么不調用Task <T> .Result僵局?

[英]Why doesn't calling Task<T>.Result deadlock?

幾個月前閱讀這篇文章之后,我變得很擅長獲取Task<T>Result ,並且使用ConfigureAwait(false)Task.Run不斷地將所有調用包裹Task.Run 但是,由於某種原因,以下代碼成功完成:

public static void Main(string[] args)
{
    var arrays = DownloadMany();

    foreach (var array in arrays);
}

IEnumerable<byte[]> DownloadMany()
{
    string[] links = { "http://google.com", "http://microsoft.com", "http://apple.com" };

    using (var client = new HttpClient())
    {
        foreach (var uri in links)
        {
            Debug.WriteLine("Still here!");
            yield return client.GetByteArrayAsync(uri).Result; // Why doesn't this deadlock?
        }
    }
}

代碼打印Still here! 3次然后退出。 這是否特定於HttpClient ,可以安全地調用Result (因為編寫它的人已經使用ConfigureAwait(false)填充它)?

Task.Result只會在某些SynchronizationContext存在時阻塞。 在控制台應用程序中,沒有一個在ThreadPool上安排繼續。 就像使用ConfigureAwait(false)

例如,在UI線程中,有一個調度單個UI線程的延續。 如果您使用UI線程與Task.Result同步等待, Task.Result在UI線程上完成的任務就會出現死鎖。

此外,死鎖取決於GetByteArrayAsync的實現。 如果它是異步方法並且它等待不使用ConfigureAwait(false)則只能死鎖。

如果您願意,可以使用Stephen Cleary的AsyncContext ,它將適當的SynchronizationContext添加到您的控制台應用程序,以測試您的代碼是否可以在UI應用程序(或ASP.Net)中阻止。


關於HttpClient (以及大多數.NET)的任務返回方法:它們在技術上並不是異步的。 他們不使用asyncawait關鍵字。 他們只是返回一項任務。 通常是Task.Factory.FromAsync的包裝器。 所以無論如何它可能“安全”阻止它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM