17

我正在做一个演示文稿,并认为以下操作应该失败,因为 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);
    }
4

3 回答 3

6

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 将确保它们一次执行一个。它们可以在任何线程上执行,但该线程将具有原始页面的身份和文化。

于 2012-04-04T06:12:33.813 回答
4

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

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

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

PS 安全性总是被传播,不管ConfigureAwait- 如果你考虑一下,这是有道理的。我不确定文化,但如果它也总是被传播,我不会感到惊讶。

于 2012-04-04T13:46:04.860 回答
0

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

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

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

在之外,Controller我们无法访问此内容ControllerContext,因此我们必须使用System.Web.HttpContext具有所有警告的直播ConfigureAwait(false);

于 2019-05-15T15:10:02.603 回答