即使在Asp.Net流量使用ConfigureAwait(假)后死锁 [英] deadlock even after using ConfigureAwait(false) in Asp.Net flow
问题描述
我甚至使用后点击僵局 ConfigureAwait(假)
,下面是样品code。
I'm hitting deadlock even after using ConfigureAwait(false)
, below is the sample code.
由于每个样品<一个href=\"http://blog.stephencleary.com/2012/02/async-and-await.html\">http://blog.stephencleary.com/2012/02/async-and-await.html (#Avoding上下文),这不应该打到死锁。
As per the sample http://blog.stephencleary.com/2012/02/async-and-await.html (#Avoding Context), this should not have hit dead lock.
这是我的类
public class ProjectsRetriever
{
public string GetProjects()
{
...
var projects = this.GetProjects(uri).Result;
...
...
}
private async Task<IEnumerable<Project>> GetProjects(Uri uri)
{
return await this.projectSystem.GetProjects(uri, Constants.UserName).ConfigureAwait(false);
}
}
这个类是从一个共享库:
public class ProjectSystem
{
public async Task<IEnumerable<Project>> GetProjects(Uri uri, string userName)
{
var projectClient = this.GetHttpClient<ProjectHttpClient>(uri);
var projects = await projectClient.GetProjects();
// code here is never hit
...
}
工作,如果我加ConfigureAwait(假)等待共享库,这里的HttpClient调用时来电:
public class ProjectSystem
{
public async Task<IEnumerable<Project>> GetProjects(Uri uri, string userName)
{
var projectClient = this.GetHttpClient<ProjectHttpClient>(uri);
var projects = await projectClient.GetProjects().ConfigureAwait(false);
// no deadlock, resumes in a new thread.
...
}
我已经经历中找到的所有博客,只是我觉得不同的是ConfigureAwait(假)一起使用时,与httpClient.AsyncApi()调用!?
I've been going through all blogs found, only difference I find is ConfigureAwait(false) works when used with httpClient.AsyncApi() call!?
请帮忙澄清!
推荐答案
从注释:
我下假设,一旦ConfigureAwait(假)时(在调用堆栈中任何地方),从该点执行不会引起死锁。
I was under assumption, once ConfigureAwait(false) is used (any where in the call stack), execution from that point will not cause deadlock.
我不相信魔法,你也不应该。总是努力去理解当您在code使用的东西会发生什么。
I don't believe in black magic, and neither should you. Always strive to understand what happens when you use something in your code.
在的await
返回异步方法工作
或任务&LT; T&GT ;
,有的SynchronizationContext
的 TaskAwaitable
正在生成的隐式捕获 Task.GetAwaiter
方法。
When you await
an async method that returns a Task
or a Task<T>
, there is an implicit capture of the SynchronizationContext
by the TaskAwaitable
being generated by the Task.GetAwaiter
method.
一旦同步上下文到位,异步方法调用完成后, TaskAwaitable
试图元帅的延续(这基本上是该方法的休息后先调用的await
关键字)到的SynchronizationContext
(使用 SynchronizationContext.Post
),它是previously抓获。如果调用线程被阻塞,等待上相同的方法来完成,你有一个僵局
Once that sync context is in place and the async method call completes, the TaskAwaitable
attempts to marshal the continuation (which is basically the rest of the method calls after the first await
keyword) onto the SynchronizationContext
(using SynchronizationContext.Post
) which was previously captured. If the calling thread is blocked, waiting on that same method to finish, you have a deadlock.
您应该问自己的我应该公开为异步方法同步包装?的的答案是时间 99%没有。您应该使用同步API,比如一个 Web客户端
优惠。
You should ask yourself Should I expose synchronous wrappers for asynchronous methods? 99 percent of the time the answer is no. You should use a synchronous API, such as the one WebClient
offers.
这篇关于即使在Asp.Net流量使用ConfigureAwait(假)后死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!