为什么HttpContext.Current在等待之后为null?

wel*_*gan 82 c# asp.net async-await asp.net-web-api

我有以下测试WebAPI代码,我没有在生产中使用WebAPI但我之所以这样做是因为我对这个问题进行了讨论:WebAPI异步问题

无论如何,这是违规的WebAPI方法:

public async Task<string> Get(int id)
{
    var x = HttpContext.Current;
    if (x == null)
    {
        // not thrown
        throw new ArgumentException("HttpContext.Current is null");
    }

    await Task.Run(() => { Task.Delay(500); id = 3; });

    x = HttpContext.Current;
    if (x == null)
    {
        // thrown
        throw new ArgumentException("HttpContext.Current is null");
    }

    return "value";
}
Run Code Online (Sandbox Code Playgroud)

我曾经相信第二个异常是预期的,因为当await完成时,它可能会在一个不同的线程上,HttpContext.Current因为线程静态变量将不再解析为适当的值.现在,基于同步上下文,实际上它可能会在等待之后被强制返回到同一个线程但我在测试中没有做任何奇特的事情.这只是一个简单,天真的用法await.

在另一个问题的评论中,我被告知HttpContext.Current在等待之后应该解决.对这个问题甚至还有另一个评论,表明同样的问题.什么是真的?应该解决吗?我想不,但我想要一个权威的答案,因为asyncawait是新的,我找不到任何确定的东西.

TL; DR:HttpContext.Current可能null在一个await

Ste*_*ary 131

请确保您正在编写ASP.NET 4.5应用程序,并以4.5为目标.async并且await在ASP.NET上具有未定义的行为,除非您在4.5上运行并且正在使用新的"任务友好"同步上下文.

特别是,这意味着您必须:

  • 设置httpRuntime.targetFramework4.5,或
  • 在你的appSettings,设置aspnet:UseTaskFriendlySynchronizationContexttrue.

更多信息可在此处获得.

  • `<httpRuntime targetFramework ="4.5"/>`解决了它,感谢澄清. (23认同)
  • 我有Target框架:.NET Framework 4.5集.我不知道该告诉你什么,它在我的本地机器上肯定是空的. (3认同)
  • 我刚刚创建了一个新的ASP.NET 4.5 WebAPI项目,复制/粘贴了您的代码,并进行了测试.它对我来说很完美(没有例外被抛出).请重新检查您是否正在使用*并定位*4.5. (2认同)

Tod*_*ier 22

正如@StephenCleary正确指出的那样,你需要在web.config中使用它:

<httpRuntime targetFramework="4.5" />
Run Code Online (Sandbox Code Playgroud)

当我第一次对此进行故障排除时,我在上面进行了解决方案范围内的搜索,确认它存在于我的所有Web项目中,并很快将其视为罪魁祸首.最终我突然想到在完整的上下文中查看这些搜索结果:

<!--
  For a description of web.config changes for .NET 4.5 see http://go.microsoft.com/fwlink/?LinkId=235367.

  The following attributes can be set on the <httpRuntime> tag.
    <system.Web>
      <httpRuntime targetFramework="4.5" />
    </system.Web>
-->
Run Code Online (Sandbox Code Playgroud)

卫生署.

课程:如果将Web项目升级到4.5,则仍需要手动设置该设置.

  • 另一个问题是这与<compilation targetFramework"4.5"/>不同 (19认同)

小智 5

我最近遇到了这个问题。正如斯蒂芬指出的那样,没有明确设置目标框架会产生这个问题。

就我而言,我们的 Web API 已迁移到 4.6.2 版,但从未在 Web 配置中指定运行时目标框架,因此基本上在 <system.web> 标记中缺少此内容:

如果您对正在运行的框架版本有疑问,这可能会有所帮助:在您的任何 Web API 方法上添加以下行并设置断点以验证当前在运行时加载的类型并验证它不是旧版实现:

你应该看到这个(AspNetSynchronizationContext):

在此处输入图片说明

而不是 LegazyAspNetSynchronizationContext(这是我在添加目标框架之前看到的):

在此处输入图片说明

如果您转到源代码 ( https://referencesource.microsoft.com/#system.web/LegacyAspNetSynchronizationContext.cs ),您将看到此接口的 Legacy 实现缺少异步支持。

在此处输入图片说明

我花了很多时间试图找到问题的根源,Stephen 的回答很有帮助。希望此答案提供有关该问题的更多信息。