28

我有一个面向 .NET 4.5 的 ASP.NET MVC 4 应用程序。我们的子操作之一使用 HttpClient 调用 Web 服务。

由于我们阻塞了等待 HttpClient 响应的 IO,因此将代码转换为 async/await 模式非常有意义。但是,当 MVC 4 尝试执行子操作时,我们会收到以下错误消息:

HttpServerUtility.Execute 在等待异步操作完成时被阻塞。

乍一看,MVC 4 似乎不支持子操作中的异步/等待。剩下的唯一选择是使用同步代码运行并在异步任务上强制“等待”。

众所周知,在 ASP.NET 上下文中的异步任务上触摸 .Result 或 .Wait() 将导致立即死锁。我的异步逻辑包含在类库中,所以我不能使用“await blah.ConfigureAwait(false)”技巧。请记住,在子操作上标记“异步”并使用等待会导致错误,这会阻止我配置等待。

在这一点上,我被画到了一个角落。有没有办法在 MVC 4 子操作中使用异步方法?似乎是一个没有解决方法的完全错误。

4

2 回答 2

34

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 上下文。

于 2012-10-05T09:23:42.707 回答
7

斯蒂芬回答的格式对我来说不太适用(也许这是一个异步菜鸟问题,但是嘿)。

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

Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;
于 2016-01-27T07:47:54.770 回答