Why is HttpContext.Current null after await?
今天在对项目代码进行异步化改进的时候,遇到一个奇怪的问题(莫笑,以前没遇过),正如标题一样,HttpContext.Current 在 await 异步执行之后,就会变为 null。
演示代码:
public async Task<IEnumerable<string>> Get()
{
await DoWaitAsync();
DoWork();
return new string[] { "value1", "value2" };
}
private Task DoWaitAsync()
{
return
Task.Factory.StartNew(
() =>
{
// null !!
var httpCtx = System.Web.HttpContext.Current;
Thread.Sleep(1000);
});
}
public void DoWork()
{
//Not null
var httpCtx = System.Web.HttpContext.Current;
}
HttpContext.Current 这个东西,我们并不陌生,在进行 ASP.NET 应用程序开发的时候,我们经常会用到,比如获取当前请求的一些值,首先它是一个线程静态属性(thread-static variable),注意其中的关键字:当前请求和线程,也就是说它是和请求线程相关的,在 ASP.NET 应用程序中,一个请求线程会贯穿整个请求过程,所以我们可以在这个请求的任何地方,都可以访问到 HttpContext.Current,这也就是它的“强大之处”,但是如果涉及到异步多线程呢?就不是这么回事了,因为 HttpContext.Current 依附的是当前请求的主线程,当我们使用 await 异步执行一些代码的时候,再次执行下面的代码,其实就不是当前请求线程了,所以我们再次访问 HttpContext.Current 的时候,就变为 null 了,这个问题告诫我们,ASP.NET 应用程序中,如果进行异步化,使用 HttpContext.Current 一定要小心谨慎。
- 需要注意的是:HttpContext.Current 在没有进行 await 操作的时候,都是可以获取到值的。
如果我们的 ASP.NET 应用程序进行了异步化,然后还必须用到 HttpContext.Current,那我们该怎么解决这个问题?
解决的方式有很多,如果应用程序很简单,我们可以在 await 操作之前,先用变量存储 HttpContext.Current,用到的地方直接用这个变量就行了,当然这不是一个“解决问题”的方法,还有一种是用 Cache,可以参考:system-web-httpcontext-current-nulls-itself-after-checking-for-a-cache,我觉得这种方式也是“瞎忽悠”,没有从根本问题上进行解决。
其实想想问题的根源,就是如何在多个线程中共享一个 HttpContext.Current,这个在 MSDN 中表述为:共享/同步上下文(Synchronization Context)
You can use the TaskScheduler.FromCurrentSynchronizationContext method to specify that a task should be scheduled to run on a particular thread. This is useful in frameworks such as Windows Forms and Windows Presentation Foundation where access to user interface objects is often restricted to code that is running on the same thread on which the UI object was created. For more information, see How to: Schedule Work on a Specified Synchronization Context.
那我们如何在 ASP.NET 应用程序中,进行运用呢?答案很简单,我们只需要在 web.config 中指定 targetFramework 版本为 4.5 即可:
<httpRuntime targetFramework="4.5" />
或者在 appSettings 中添加如下 key(测试可用):
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
参考资料:
- Why HttpContext.Current be null?
- Why is HttpContext.Current null after await?
- Why thread context does not flow to background thread in async/await?
- HttpContext.Current并非无处不在
Why is HttpContext.Current null after await?的更多相关文章
- Why is HttpContext.Current null during the Session_End event?
Why is HttpContext.Current null during the Session_End event? On Session_End there is no communicati ...
- ASP.NET多线程下使用HttpContext.Current为null解决方案 2015-01-22 15:23 349人阅读 评论(0) 收藏
问题一:多线程下获取文件绝对路径 当我们使用HttpContext.Current.Server.MapPath(strPath)获取绝对路径时HttpContext.Current为null,解决办 ...
- ASP.NET多线程下使用HttpContext.Current为null解决方案 2015-01-22 15:23 350人阅读 评论(0) 收藏
问题一:多线程下获取文件绝对路径 当我们使用HttpContext.Current.Server.MapPath(strPath)获取绝对路径时HttpContext.Current为null,解决办 ...
- 多线程中使用HttpContext.Current为null的解决办法
HttpContext.Current.Server.MapPath(logFile) 这个是得到具体路径的方法 正常情况下是可以的 多线程情况下就为null 下边的代码原本的作用是把网站的异常 ...
- HttpContext.Current and Web Api
Using HttpContext.Current in WebApi is dangerous because of async HttpContext.Current gets the curre ...
- HttpContext.Current.Server.MapPath("") 未将对象设置到引用的
在多线程中使用该方法获取目录报错:未将对象设置到引用 #region 上传图片到腾讯 public async Task<Result> UploadImageToWX(string ba ...
- 我所知道的HttpContext.Current
在MVC中,HttpContext.Current是比较常见的对象,可以用它来进行Session,Cache等的保存等.但是它并不是无处不在的,下面就慢慢来揭开它的面纱. 当我们向服务端发送请求的时候 ...
- System.Web.HttpContext.Current.Server.MapPath("~/upload/SH") 未将对象引用设置为实例对象
做项目的时候,System.Web.HttpContext.Current.Server.MapPath("~/upload/SH") 获取路径本来这个方法用的好好的 因为需要 ...
- HttpContext.Current.Server.MapPath("/") 未将对象设置到对象的实例异常。
多线程中的System.Web.HttpContext.Current.Server.MapPath("/") 多线程中Server.MapPath会失效... 网上找到几种解决方 ...
随机推荐
- jsp和mysql乱码
jsp页面,mysql页面上的中文不显示为乱码,各个地方使用的编码(如UTF-8,GB18030,GBK等)的编码保持一致即可. 1. jsp页面的编码: <%@page language=&q ...
- vue-cli 路由 实现类似tab切换效果(vue 2.0)
1,更改main.js 2,在App.vue中,写入两个跳转链接(router-link),分别跳转到"home""About" (home.About即分别是 ...
- CentOS6.5安装中文输入法
首先进入命令形式的客户端 切换成root用户,输入命令"su root"即可,接着输入 yum install "@Chinese Support" 命令按en ...
- 2016/11/16 周三 <使用LocalStore记住用户密码方法示例>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- 浅谈Js闭包现象
一.1.我们探究这个问题的时候如果按照正常的思维顺序,需要知道闭包是什么它是什么意思,但是这样做会让我们很困惑,了解这个问题我们需要知道它的来源,就是我们为什么要使用闭包,先不管它是什么意思! ...
- ASP.NET Identity 2新增双重认证、帐号锁定、防伪印章功能并修复了一些bug
Microsoft最近发布了ASP.NET Identity 2,该版本支持双重认证.帐号锁定以及防伪印章功能,还增强了用户帐号和索引.此外新版本还包含一个改进的密码验证器并修复了一些bug. 借助于 ...
- Java工作环境笔记
环境 1. Jvm最简生存指南: http://www.importnew.com/10127.html 2. 所有路径中,不要出现中文,即使开始的时候,调试Tomcat时,路径有中文也可以,你真不知 ...
- 推荐:图片轮播插件Nivo Slider
因为项目需要一款切换样式多一些的轮播插件,不经意找到了NivoSlider,非常好用,比bootstrap要好用,而且样式丰富.值得注意的是,这款插件是在MIT协议下免费的. ...
- OpenGL快问快答
OpenGL快问快答 本文内容主要来自对(http://www.opengl.org/wiki/FAQ)的翻译,随机加入了本人的观点.与原文相比,章节未必完整,含义未必雷同,顺序未必一致.仅供参考. ...
- 干货!表达式树解析"框架"(2)
最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 为了过个好年,我还是赶快把这篇完成了吧 声明 本文内容需要有一定 ...