[英]In the context of ASP.NET, why doesn't Task.Run(…).Result deadlock when calling an async method?
[英]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)的任務返回方法:它們在技術上並不是異步的。 他們不使用async
和await
關鍵字。 他們只是返回一項任務。 通常是Task.Factory.FromAsync
的包裝器。 所以無論如何它可能“安全”阻止它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.