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会失效... 网上找到几种解决方 ...
随机推荐
- 李洪强经典面试题152-Runtime
李洪强经典面试题152-Runtime Runtime Runtime是什么 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码, ...
- Python swapcase()方法
首先,要明白Python swapcase() 方法用于对字符串的大小写字母进行转换. 其次,了解swapcase()方法语法:str.swapcase() 返回值:返回大小写字母转换后生成的新字符串 ...
- while(cin.eof)出错 poj
zoj遇到c++如何判定输入流结尾的问题,一不小心就超时了 楼下的代码可以通过zoj #include<iostream> using namespace std; int main(){ ...
- CSS篇之DIV+CSS布局
<div></div> div与其他标签一样,也是一个XHTML所支持的标签. div是XHTML中指定的,远门用于布局设计的容器标记. 简单的CSS布局 头部 内容 页脚 & ...
- 在java中如何用键盘输入一个数,字符,字符串
一,利用 Scanner 实现从键盘读入integer或float 型数据 import java.util.*; public class test { public static void mai ...
- python字符串的使用
之前在网上看了关于python最基础的一些教程,看着都通俗易懂,但是在写的过程中却感觉还是很生涩.关于字符串的使用还是应该多写多练!如何将“teacher_id = 123 #老师ID”转换成字典或者 ...
- ABP理论学习之缓存Caching
返回总目录 本篇目录 介绍 ICacheManager ICache ITypedCache 配置 介绍 ABP提供了缓存的抽象,它内部使用了这个缓存抽象.虽然默认的实现使用了MemoryCache, ...
- Nova PhoneGap框架 第三章 页面
页面在项目架构中是一个很重要的概念,它让我们能够将一个功能复杂的项目拆分成一个一个功能比较独立的小区域,这极大的提高了代码的可读性和可维护性. 在我们这个框架中,一个页面由JS和HTML两部分组成,首 ...
- 分享我们项目中基于EF事务机制的架构
写在前面: 1. 本文中单元测试用到的数据库,在执行测试之前,会被清空,即使用空数据库. 2. 本文中的单元测试都是正确通过的. 要理解EF的事务机制,首先要理解这2个类:TransactionSco ...
- 浅析用Base64编码的图片优化网页加载速度
想必大家都知道网页加载的过程,从开始请求,到加载页面,开始解析和显示网页,遇到图片就再次向服务器发送请求,加载图片.如果图片很多的话,就会产生大量的http请求,从而影响页面的加载速度.所以现在有一种 ...