我正在寫一些MVC4異步控制器代碼,並且遇到了一個問題,因此我會向兩個長時間運行的Web服務異步調用,而第二個調用看起來是在錯誤的線程中。在多個等待場景中的HTTPContext
這裏是代碼片段:
public async Task<ActionResult> AmendDetails(Model model)
{
ClientMaintenanceClient clientService = new ClientMaintenanceClient();
UpdateResponse clientResponse = await clientService.GetForUpdateAsync(clientService.CreateRequest(model.Id));
StaticDataEnquiryClient staticService = new StaticDataEnquiryClient();
DataResponse staticResponse = await staticService.GetPayMethodsAsync(staticService.CreateRequest());
...
}
實質上,要的createRequest()的調用將查找會話標識出的HttpContext,並創建一個呼叫中使用該服務所形成的WCF請求對象。
然而在執行時,第一個調用很好,但第二個異步調用失敗,因爲HttpContext爲null,這會導致我相信我現在處於不同的線程。
當我在MVC3和.Net4.5之前完成此操作時,必須通過AsyncManager(使用EAP)從異步調用中返回時手動同步線程,但我認爲我不再需要這樣做TAP。
如果我並行執行代碼,使用下面的代碼片段,問題就會消失。
public async Task<ActionResult> AmendDetails(Model model)
{
ClientMaintenanceClient clientService = new ClientMaintenanceClient();
var clientTask = clientService.GetForUpdateAsync(clientService.CreateRequest(model.Id));
StaticDataEnquiryClient staticService = new StaticDataEnquiryClient();
var staticTask = staticService.GetPayMethodsAsync(staticService.CreateRequest());
await Task.WhenAll(clientTask,staticTask);
UpdateResponse clientResponse = await clientTask;
DataResponse staticResponse = await StaticTask;
...
}
我假設的是,在第一個片段,第一個是AWAIT過程的時候我到了第二的await移動到後臺線程,等於是,我仍然在後臺線程。 HttpContext將爲空,因爲我無法從該線程獲得它。
我還假設在第二段代碼中,我在第一次等待之前做了所有的HTTPContext查找,所以我從來沒有將HTTPContext看作null,因爲我從不從後臺線程調用它。
任何人都可以證實我的上述假設?我不想在我的代碼中看到一個明顯的錯誤,它會在以後回來並咬我!
更新:
我決定在這裏檢查執行過程中的線程,它出現第二的await確實在不同的線程比第一的await發生。有趣的是,在第二次調用時,看起來HttpContext不爲空。它是空的HttpContext.Current。
我通過訪問會話ID:
HttpContext.Current.Session.SessionId
我猜我需要第二的await在什麼地方同步的東西,但我不知道是什麼。
在ASP.NET中,線程不喜歡GUI應用程序。你的第二個調用應該在正確的上下文中執行,同時設置HttpContext。 (換句話說,我不知道你的代碼有什麼問題。) – svick 2013-04-22 16:53:48