我正在写一些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