2012-04-04 64 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