【发布时间】:2013-04-15 15:28:45
【问题描述】:
我正在编写一些 MVC4 异步控制器代码,并且遇到了一个问题,即我异步调用了两个长时间运行的 Web 服务,而第二个调用似乎在错误的线程上。
这里是sn-p的代码:
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 中查找会话 ID,并创建用于调用服务的已形成的 WCF 请求对象。
然而,在执行时,第一次调用正常,但是第二次异步调用失败,因为 HttpContext 为空,这会让我相信我现在在不同的线程上。
当我在 MVC3 和 .Net4.5 之前执行此操作时,我必须在通过 AsyncManager(使用 EAP)从 Async 调用返回时手动同步线程,但我认为我不再需要使用 TAP 执行此操作.
如果我使用下面的代码 sn-p 并行执行代码,问题就会消失。
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;
...
}
我假设在第一个 sn-p 中,第一个 await 正在将进程移动到后台线程,因此当我到达第二个 await 时,我仍然在后台线程上. HttpContext 将是空的,因为我无法从那个线程访问它。
我还假设在第二个 sn-p 代码中,我在第一个 await 之前执行了所有 HTTPContext 查找,所以我从来没有看到 HTTPContext 为空,因为我从来没有从后台调用它线程。
谁能证实我上面的假设?我不想在我的代码中查看一个明显的错误,它稍后会回来咬我!
更新:
我决定在这里执行期间检查线程,看来第二次等待确实发生在与第一次等待不同的线程上。有趣的是,似乎 HttpContext 在第二次调用时不为空。 HttpContext.Current 为空。
我正在通过以下方式访问会话 ID:
HttpContext.Current.Session.SessionId
我猜我需要在第二次等待之前同步某处,但我不确定是什么。
【问题讨论】:
-
在 ASP.NET 中,线程不像在 GUI 应用程序中那样工作。您的第二次调用应该在正确的上下文中执行,并设置
HttpContext。 (换句话说,我不知道你的代码有什么问题。)
标签: c# asp.net-mvc-4 asynchronous c#-5.0