【问题标题】:HTTPContext in multiple await scenario多个等待场景中的 HTTPContext
【发布时间】: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


【解决方案1】:

您的代码绝对应该工作。既然您提到了 MVC 3,我假设这是一个升级项目。在这种情况下,请确保您的 web.config 中有以下内容:

<appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>

【讨论】:

  • 嗯...是的,工作。它做了什么? MSDN 声明 "Setting this compatibility switch is mandatory for WebSockets-enabled applications, for using Task-based asynchrony in Web Forms pages, and for certain other asynchronous behaviors." 这是某些其他异步行为吗?
  • 说实话,我不能 100% 确定为什么您的代码在新的(任务友好的)AspNetSynchronizationContext 和旧的LegacyAspNetSynchronziationContext 之间的工作方式不同。我怀疑对于旧版本,它太早完成了请求-但我认为async MVC 控制器会阻止...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-15
  • 2018-03-10
  • 2016-07-15
  • 2012-08-02
  • 2016-11-05
相关资源
最近更新 更多