从ASP.NET MVC操作调用ConfigureAwait

asp.net-mvc-4 async-await

3473 观看

3回复

2329 作者的声誉

我正在编写演示文稿,并认为以下内容应该失败,因为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);
    }
作者: Dan Friedman 的来源 发布者: 2012 年 4 月 4 日

回应 (3)


6

11856 作者的声誉

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

Stephen Toub在MSDN文章中提到了这一点

Windows窗体不是提供SynchronizationContext派生类的唯一环境。ASP.NET还提供了一个AspNetSynchronizationContext,虽然它不公开,不适合外部消费。相反,ASP.NET使用它来促进ASP.NET 2.0中的异步页面功能(有关更多信息,请参阅msdn.microsoft.com/msdnmag/issues/05/10/WickedCode)。此实现允许ASP.NET在完成所有未完成的异步调用之前阻止页面处理完成

有关同步上下文的更多详细信息,请参阅Stephen Cleary去年的文章

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

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

作者: James Manning 发布者: 04.04.2012 06:12

4

301350 作者的声誉

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

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

我目前无法对此进行测试,但如果您使用System.Web.HttpContext.Current而不是,我希望它会失败HttpContext

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

作者: Stephen Cleary 发布者: 04.04.2012 01:46

0

10964 作者的声誉

看起来是因为Controller捕获了Context,而使用System.Web.HttpContext是对同步上下文的一部分的实时访问。

如果我们查看ASP.NET MVC5源代码,我们可以看到ControllerBase所有控制器继承的类都有自己ControllerContext的类RequestContext

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

Controller我们之外我们没有访问权限,ControllerContext因此我们必须使用System.Web.HttpContext具有所有注意事项的live ConfigureAwait(false);

作者: seangwright 发布者: 15.05.2019 03:10
32x32