假设我正在编写一个自定义MVC过滤器,该过滤器在方法重载中执行一些异步调用,如下所示:
为什么
public class MyActionFilter : System.Web.Mvc.ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext ctx)
{
var stuff = ConfigureAwaitHelper1().Result;
// do stuff
}
public override void OnActionExecuting(ActionExecutingContext ctx)
{
var stuff = ConfigureAwaitHelper2().Result;
// do stuff
}
private async Task<string> ConfigureAwaitHelper1()
{
var result = await client.GetAsStringAsync("blah.com").ConfigureAwait(false);
return result;
}
private async Task<string> ConfigureAwaitHelper2()
{
return await client.GetAsStringAsync("blah.com").ConfigureAwait(false);
}
}
为什么
OnActionExecuting
会死锁,而 OnActionExecuted
却不会?我看不到两者之间的根本区别。返回操作只会在异步任务完成后进行,这有点像将结果放入“匿名返回”局部变量中再返回它,所以我不明白为什么前者会死锁。
.ConfigureAwait(false)
,如果要实际上让你在不死锁的情况下执行.Result
,则必须在其上设置.ConfigureAwait(false)
。如果单个 await 没有设置并且该 await 是导致继续发生的 await,则会发生死锁。您需要展示client.GetAsStringAsync
的代码以及其下的每个 async/await 调用,直到找到仍具有上下文数据的调用。 - Scott ChamberlainActionFilterAttribute
是同步的,而且我无法控制client
。我知道你担心一路做下去,但让我们假设这个示例已经完成了,并且在client.GetAsStringAsync()
内部没有进一步配置的内容。 - gzakOnActionExecuting
死锁了而不是OnActionExecuted
吗? - Diegoclient.GetAsStringAsync()
方法中删除了async/await关键字,直接返回原始任务。在她的情况下,她看到了这里描述的行为。 - gzak