Jam*_* Ko 7 c# deadlock asynchronous async-await dotnet-httpclient
几个月前读完这篇文章之后,我变得妄想得到Result一个Task<T>并且用一个ConfigureAwait(false)或者不停地包裹我的所有电话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?
}
}
}
Run Code Online (Sandbox Code Playgroud)
代码打印Still here!3次然后退出.这是否特定于HttpClient它是安全的Result(如在编写它的人已经用它ConfigureAwait(false))?
i3a*_*non 10
Task.Result只会在某些SynchronizationContexts 存在的情况下阻止.在控制台应用程序中没有一个如此延续安排在ThreadPool.就像他们使用时一样ConfigureAwait(false).
例如,在UI线程中,有一个调度单个UI线程的延续.如果您Task.Result使用UI线程同步等待,那么只能在UI线程上完成的任务就会出现死锁.
而且,死锁取决于执行情况GetByteArrayAsync.如果它是异步方法并且它等待不使用,则只能死锁ConfigureAwait(false).
如果你愿意,你可以使用Stephen Cleary AsyncContext,它可以SynchronizationContext为你的控制台应用添加一个适当的代码来测试你的代码是否可以在UI应用程序(或ASP.Net)中阻止.
关于HttpClient(和大多数.NET的)任务返回方法:它们在技术上不是异步的.他们不使用async和await关键字.他们只是返回一项任务.通常是一个包装器Task.Factory.FromAsync.所以无论如何它可能"安全"阻止它们.
| 归档时间: |
|
| 查看次数: |
2375 次 |
| 最近记录: |