ASP.NET MVC 4异步子操作

Sha*_*ser 28 asp.net-mvc async-await asp.net-mvc-4

我有一个针对.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.

Ste*_*ary 33

还有一部分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) { ... }
Run Code Online (Sandbox Code Playgroud)

效果类似于ConfigureAwait(false):由于MyHttpRequest在线程池上下文中运行,因此在完成时不会尝试进入ASP.NET上下文.

  • 我学到的一个有趣的优化是将".Result"替换为".GetAwaiter().GetResult()".避免AggregateException混乱. (5认同)
  • 在异步上查看了一些更高级的MSDN/Channel 9视频,并看到了完全相同的建议.我已经更新了代码并切换到阻止子操作中的任务 - 绝对不是理想的,但它确实有效.希望他们将来能解决这个问题.我会投票支持用户的声音:)谢谢! (3认同)
  • 注意相关的CodePlex上和UserVoice的链接http://aspnetwebstack.codeplex.com/workitem/601和http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/3233329-support-asynchronous-儿童的行动.请投票. (3认同)

Dav*_*nce 6

斯蒂芬答案的格式对我来说并不适用(也许这是一个异步的noob问题,但是嘿).

我必须以这种格式编写异步表达式以获得强类型返回值.

Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;
Run Code Online (Sandbox Code Playgroud)