【问题标题】:MVC controller can't execute Async methodMVC 控制器无法执行异步方法
【发布时间】:2015-07-05 04:56:36
【问题描述】:

我有一个非常基本的 MVC 控制器,只有一个动作:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        OpenConnection().Wait();

        return View();
    }

    private async Task OpenConnection()
    {
        var synchronizationContext = SynchronizationContext.Current;
        Debug.Assert(synchronizationContext != null);

        using (
            var connection =
                new SqlConnection(
                    @"Data Source=(localdb)\ProjectsV12;Initial Catalog=Database1;Integrated Security=True;"))
        {
            await connection.OpenAsync(); // this always hangs up                
        }
    }
}

问题是常规操作(不是异步版本)无法执行异步方法。在我的情况下,OpenConnection() 方法总是挂在 await connection.OpenAsync() 行。

一段时间后,我找到了两种使这段代码正常工作的方法。

  1. 使控制器的动作异步

    public async Task<ActionResult> Index()
    {
        await OpenConnection();
    
        return View();
    }
    
  2. 或者允许异步执行而不捕获原始 SychronizationContext - 为此:

    await connection.OpenAsync();

    替换为:

    await connection.OpenAsync().ConfigureAwait(false);

所以,我的猜测是我最初的问题是在 SynchronizationContext 附近的某个地方。但是 SynchronizationContext.Current 不为空,这让我怀疑我的猜测是否正确。

那么,谁能解释一下,为什么 MVC 控制器中的 not async 动作不能同步执行异步方法?

【问题讨论】:

    标签: c# asp.net-mvc-4 async-await task


    【解决方案1】:

    Stephen Cleary 有一个good blog post about this issue,它会影响 ASP.NET 和桌面应用程序。基本要点是,因为上下文(在您的示例中为 ASP.NET 请求上下文)正在被显式 .Wait() 调用同步阻止,所以异步任务无法在上下文上运行代码以通知它已完成,所以它死锁了。

    他还提出了与您相同的两种解决方案(从顶级控制器方法一直向下使用异步或更改您的异步“库”代码以不捕获上下文)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-15
      • 2017-05-19
      • 1970-01-01
      相关资源
      最近更新 更多