使用异步操作运行同步代码

Posted

技术标签:

【中文标题】使用异步操作运行同步代码【英文标题】:Using an Async Action to Run Synchronous Code 【发布时间】:2012-03-09 00:38:53 【问题描述】:

我有一个搜索操作,它有两个路径,一个是同步路径,它只返回一个简单的视图,另一个是异步路径,它异步执行搜索然后返回一个视图。两者都是 GET 请求,因此它们是同一操作的一部分。

问题是当我访问操作“localhost:XXXX/Home/Search”时,页面只是无限加载。使用 Fiddler,我可以看到请求永远不会返回。我已经对其进行了调试,它到达了最后一行代码,但是,请求再次没有完成。

我已将复制简化为以下内容:

public async Task<ActionResult> Search() 
 
    return View(); 
 

VS11 警告我代码将在没有等待的情况下同步运行,这很好,但请求没有完成。

这应该有效吗?还是我需要在这里做点别的?

编辑

这是面向 .NET 4.5 的 MVC 4。

编辑 2

对于那些在代码中看得更清楚的人,这就是我需要在异步操作中同步的原因:

public async Task<ActionResult> Search(string query = null)

    if (string.IsNullOrWhiteSpace(query))
        return View(new SearchViewModel());   // never loads

    var model = await _someService.SearchAsync(query);
    return View(model);    // loads

【问题讨论】:

我认为这应该工作,但由于某种原因没有。由于它在内部抛出并捕获 NullReferenceExcpetion,我认为这是一个错误。 提示:如果您的操作方法返回 Task&lt;T&gt;,请确保您继承自 AsyncController,而不是 Controller 2@vcsjones,我试过了,但没有帮助。还有it shouldn't be necessary in MVC4. @svick - 也许在测试版中已经改变了,但它必需的。那我得做点修修补补了。 好问题,好研究。 【参考方案1】:

这是测试版中的一个已知错误。 To quote Stephen Toub:

简短的回答是 .NET 4.5 Beta 中的 ASP.NET MVC 中存在一个已知错误,当​​异步方法同步完成时会导致此问题。在修复可用之前,一个简单的解决方法是添加“await Task.Yield();”作为 async 方法的第一行,强制它异步完成。为了使其正常工作,您还需要确保您使用的是 .NET 4.5 中 ASP.NET 提供的新 SynchronizationContext,这意味着您有以下行:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

在配置文件的 appSettings 部分中。

【讨论】:

以上是关于使用异步操作运行同步代码的主要内容,如果未能解决你的问题,请参考以下文章

同步/异步 异步回调 协成 线程队列

异步IO和协程

在异步控制器中使用同步操作

期约与异步函数

JavaScript 异步操作之回调函数

代码如何在同步的单核CPU上异步?