当前位置: 首页 > 知识库问答 >
问题:

为什么Await后HttpContext.Current为空?

黄跃
2023-03-14

我有以下测试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";
}

因此,我认为第二个异常是预期的,因为当await完成时,它很可能位于另一个线程上,其中HttpContext.Current作为线程静态变量将不再解析为适当的值。现在,基于同步上下文,它实际上可以在await之后被强制返回到相同的线程,但我在测试中没有做任何花哨的事情。这只是对await的简单、幼稚的使用。

在另一个问题的注释中,我被告知httpcontext.current应该在等待后解决。甚至还有一个关于这个问题的评论也表明了同样的观点。那么什么是真的?它能解决吗?我想没有,但我想要一个权威的答案,因为asyncawait是新的,我找不到任何确定的东西。

TL;DR:HttpContext.CurrentAwait之后是否可能为空

共有3个答案

周伟泽
2023-03-14

是我的测试有缺陷,还是我缺少了一些web.config元素,它可以在等待后使HttpContext.Current正确解析?

您的测试没有缺陷,并且在等待之后的HttpContext.Current不应为null,因为在ASP.NET Web API中,当您等待时,这将确保在此等待之后的代码传递的是在等待之前存在的正确的HttpContext。

吉俊德
2023-03-14

正如@Stephencleary所正确指出的,您需要在web.config中提供以下内容:

<httpRuntime targetFramework="4.5" />

当我第一次对此进行故障排除时,我在解决方案范围内搜索了上述内容,确认它存在于我的所有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>
-->

多伊。

教训:如果您将一个web项目升级到4.5,您仍然需要手动进行设置。

长孙星汉
2023-03-14

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

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

  • httpRuntime.targetFramework设置为4.5
  • AppSettings中,将aspnet:UseTaskFriendlySynchronizationContext设置为true

更多信息请参阅此处。

 类似资料:
  • 尝试学习Async/await(以下代码),等待在2s后返回用户名。(返回一个promise)然后只记录接收到的用户名。 问题是then方法中的记录了。 不确定这里出了什么问题。很感谢解释一下这里到底发生了什么。 多谢了。

  • 问题内容: 我在ReactJS项目中一直在使用babel的async await。我发现可以方便地与React setState一起使用,我想更好地理解它。考虑以下代码: 我的意图是让异步验证代码在组件更新后运行。而且有效!生成的控制台日志显示: 验证代码仅在handleChange更新状态并呈现新状态后运行。 通常要在状态更新后运行代码,您必须在this.setState之后使用回调。这意味着,

  • 我得到以下警告... 警告1此异步方法缺少await运算符,将同步运行。考虑使用'await'运算符来等待非阻塞API调用,或者使用'await task.run(...)'在后台线程上执行CPU绑定的工作。

  • 问题内容: 我一直在使用“ if”来测试自己的版本,并且一切似乎都正常。当然,如果使用signalAll()而不是signal(),这将导致严重崩溃,但是如果一次仅通知一个线程,这怎么会出错? 他们的代码在这里 -检查put()和take()方法;在Condition的JavaDoc顶部可以看到一个更简单,更重点的实现。 下面是我实施的相关部分。 PS我知道,通常,尤其是在这样的lib类中,应该让

  • 我知道如果我们有这样的try-catch设置: 如果中存在错误,捕获错误将触发。 根据我的理解,如果我们尝试像这样的catch设置: 如果中存在错误,则不会触发捕获错误,因为该函数将在以后运行。 我不明白的是,当我们使用wait时,为什么catch错误不会触发: 如果这次异步函数中出现错误,并且由于javascript引擎正在等待它完成运行,为什么在出现错误时它不能捕获错误呢。 编辑1: 第二个功