我有一个针对.NET 4.5的ASP.NET MVC 4应用程序。我们的一个子操作使用HttpClient调用Web服务。
由于我们阻止IO等待HttpClient响应,因此将代码转换为async / await模式非常有意义。但是,当MVC 4尝试执行子操作时,我们收到以下错误消息:
HttpServerUtility.Execute在等待异步操作完成时被阻止。
乍一看,似乎MVC 4不支持子动作中的异步/等待。唯一剩下的选择是使用同步代码运行并在异步任务上强制“等待”。
众所周知,在ASP.NET上下文中的异步任务上触摸.Result或.Wait()会导致立即死锁。我的异步逻辑包含在类库中,所以我不能使用“await blah.ConfigureAwait(false)”技巧。请记住,在子操作上标记“async”并使用await会导致错误,这会阻止我配置await。
此时我被画成了一个角落。是否任何方式在MVC 4子操作中使用异步方法?看起来像一个没有解决方法的平坦的bug。
答案 0 :(得分:32)
仍然有一部分MVC不是async
- 友好的;我希望将来能够解决这些问题。请为此创建Connect或UserVoice问题。
我的异步逻辑包含在类库中,所以我不能使用“await blah.ConfigureAwait(false)”技巧。
您可能应将ConfigureAwait(false)
添加到您的类库中的调用中(如果可以的话)。
你也可以破解另一种解决方案。 如果你的类库方法不需要ASP.NET上下文,那么你可以有一个线程池线程做(a)等你:
try
{
var result = Task.Run(async () => { await MyHttpRequest(...); }).Result;
}
catch (AggregateException ex) { ... }
效果类似于ConfigureAwait(false)
:由于MyHttpRequest
在线程池上下文中运行,因此在完成时不会尝试进入ASP.NET上下文。
答案 1 :(得分:5)
斯蒂芬的回答格式对我来说并不合适(也许这是一个异步的noob问题,但是嘿)。
我必须以这种格式编写异步表达式以获得强类型返回值。
Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;