【发布时间】:2014-08-31 03:18:14
【问题描述】:
即使在使用ConfigureAwait(false) 之后我也遇到了死锁,下面是示例代码。
根据示例http://blog.stephencleary.com/2012/02/async-and-await.html(#Avoding Context),这不应该遇到死锁。
这是我的课:
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(false) 来等待调用,则工作,其中进行 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(false) 在与 httpClient.AsyncApi() 调用一起使用时有效!?
请帮忙澄清!!!
【问题讨论】:
-
您的标题显示 *"即使使用
ConfigureAwait(false),它也不起作用,但在您的代码中,您说第二个示例有效。它是哪一个? -
@Yuval Itzchakov:在
ProjectsRetriever中使用时不起作用,在ProjectSystem中使用时起作用 -
@user2746890:
I was under assumption, once ConfigureAwait(false) is used (any where in the call stack), execution from that point will not cause deadlock.它不会捕获等待的上下文。但是打破你的调用和等待,你会发现ProjectSystem.GetProjects在GetProjects返回的任务上在调用ConfigureAwait(false)之前被调用(并等待)。 IMO 的最佳答案是“仅提供异步 API”,即使ProjectsRetriever.GetProjects()异步。 -
我现在明白了。非常感谢您澄清 Stephen/Khanh/Yuval!
-
我不明白这篇文章。
GetProjects()(没有参数的重载) 不是async并且不返回Task,所以你不能在它上面使用await。此代码甚至无效。
标签: c# asp.net async-await task-parallel-library deadlock