2012-04-04 68 views
15

我正在处理一个演示文稿,并认为由于ActionResult未在正确的上下文中返回,因此以下内容应该失败。我已经用VS测试了它,并没有发现错误。我已经调试过它并知道它正在切换线程。所以它似乎是合法的代码。从ASP.NET MVC中调用ConfigureAwait操作

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); 
    } 
+2

一个正确的答案应该说为什么这样做完全没问题,或者应该给出一个当你尝试这个时失败的例子。我的直觉告诉我,我不应该这样做,但我希望有事实支持我。 – 2012-04-05 02:55:42

回答

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

+0

在基于事件的异步,处理未完成的异步调用的应用,但它似乎并没有在任务型异步应用,因为不会有在行动结束任何悬而未决的调用。另外,通过调试,我发现用户的表单标识及其语言(安全性和文化)在ConfigureAwait之后仍然完好无损。所以我正在阅读SyncContext的原因,但似乎没有任何问题。我能做些什么来证明ConfigureAwait不应该在这里使用? – 2012-04-04 13:00:00

4

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

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

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

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

+0

是的,我的变量将永远是有效的,因为他们只是被包装到堆栈中。但即使System.Web.HttpContext.Current仍然有有效和正确的数据。 – 2012-04-05 02:51:50

+0

'BackendCall'是否同步返回? – 2012-04-06 14:43:39

+0

不是。除了逻辑检查,我已经调试过它并观察它切换线程。 – 2012-04-07 01:42:21