从ASP.NET MVC操作调用ConfigureAwait

时间:2012-04-04 03:52:33

标签: asp.net-mvc-4 async-await

我正在撰写演示文稿并认为以下内容应该失败,因为ActionResult没有在正确的上下文中返回。我用VS加载测试它并没有错误。我调试了它,知道它正在切换线程。所以它似乎是合法的代码。

ASP.NET不关心客户端应用程序上的上下文或线程吗?如果是这样,AspNetSynchronizationContext提供了什么目的?我觉得在行动本身中放置一个ConfigureAwait是不对的。这件事似乎有些不对劲。谁能解释一下?

    public async Task<ActionResult> AsyncWithBackendTest()
    {
        var result = await BackendCall().ConfigureAwait(false);
        var server = HttpContext.Server;
        HttpContext.Cache["hello"] = "world";
        return Content(result);
    }

3 个答案:

答案 0 :(得分:6)

ASP.NET没有许多客户端应用程序所需的“UI线程”(由于它下面的UI框架)。该上下文不是关于线程关联,而是跟踪页面进度(以及其他事情,如携带请求的安全上下文)

Stephen Toub mentions this in an MSDN article

  

Windows窗体不是唯一提供的窗体   SynchronizationContext派生类。 ASP.NET还提供了一个,   AspNetSynchronizationContext虽然不公开,但并不意味着   用于外部消费。相反,它是在封面下使用的   ASP.NET可以方便ASP.NET中的异步页面功能   2.0(有关更多信息,请参阅msdn.microsoft.com/msdnmag/issues/05/10/WickedCode)。这个   实现允许ASP.NET阻止页面处理完成   直到所有未完成的异步调用都已完成

Stephen Cleary's article from last year中提供了有关同步上下文的更多细节。

图4特别表明它没有WinForms / WPF的“特定线程”行为,但整个过程是一个很好的阅读。

  

如果同一个应用程序同时完成多个操作,   AspNetSynchronizationContext将确保它们在a处执行一个   时间。它们可以在任何线程上执行,但该线程将具有   原始页面的身份和文化。

答案 1 :(得分:4)

在您的代码中,HttpContext是您的AsyncController基类的成员。它不是执行线程的当前上下文。

此外,在您的情况下,HttpContext仍然有效,因为请求尚未完成。

我目前无法对此进行测试,但如果您使用System.Web.HttpContext.Current代替HttpContext,我预计会失败。

P.S。无论ConfigureAwait如何,安全总是传播 - 如果您考虑它,这是有道理的。我不确定文化,但如果它总是传播我也不会感到惊讶。

答案 2 :(得分:0)

出现该消息是因为控制器捕获了上下文,而使用System.Web.HttpContext则是对同步上下文一部分的实时访问。

如果我们查看enter link description here,我们会发现所有控制器继承的ControllerBase类都有自己的ControllerContext,它是根据RequestContext构建的。

我认为这意味着,在ConfigureAwait(false);之后丢失同步上下文的情况下,Controller的状态在发生连续的情况下仍然可以从继续之前访问控件的状态通过关闭。

Controller之外,我们无权访问此ControllerContext,因此我们必须使用实时System.Web.HttpContext,其中包含ConfigureAwait(false);的所有警告。