今天在对项目代码进行异步化改进的时候,遇到一个奇怪的问题(莫笑,以前没遇过),正如标题一样,HttpContext.Current 在 await 异步执行之后,就会变为 null。

演示代码:

       public async Task<IEnumerable<string>> Get(){await DoWaitAsync();DoWork();return  new string[] { "value1", "value2" };}private Task DoWaitAsync(){returnTask.Factory.StartNew(() => {// null !!var httpCtx = System.Web.HttpContext.Current;Thread.Sleep(1000);});}public void DoWork(){//Not nullvar 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?相关推荐

  1. HttpContext 来源(System.Web.HttpContext.Current值为null的问题)

    转大神文档:https://www.cnblogs.com/linJie1930906722/p/5708966.html ASP.NET提供了静态属性System.Web.HttpContext.C ...

  2. System.Web.HttpContext.Current.Session为NULL解决方法

    http://www.cnblogs.com/tianguook/archive/2010/09/27/1836988.html 自定义 HTTP 处理程序,从IHttpHandler继承,在写Sys ...

  3. 异步 HttpContext.Current 为空null 另一种解决方法

    异步 HttpContext.Current 为空null 另一种解决方法 参考文章: (1)异步 HttpContext.Current 为空null 另一种解决方法 (2)https://www. ...

  4. HttpContext.Current:异步模式下的疑似陷阱之源

    最近园子里首页有好几篇文章都是讲异步编程的,尤其是几篇讲博客园自身的异步化建设的文章,看了以后很有收获. 闲暇之余再重新查查资料温故知新学习一遍,重新认识了SynchronizationContext ...

  5. HttpContext.Current.Cache 过期时间

    HttpContext.Current.Cache 过期时间 原文:HttpContext.Current.Cache 过期时间 为了更快的读取数据,我们一般会把常用到的数据加载到Cache中 在.N ...

  6. HttpContext.Current.Cache vs. HttpRuntime.Cache

    .NET中Cache有两种调用方式:HttpContext.Current.Cache 和 HttpRuntime.Cache,这两种方式有什么区别呢?我们先看MSDN上的解释:       Http ...

  7. HttpContext.Current.Cache和HttpRuntime.Cache的区别,以及System.Runtime.Caching

    先看MSDN上的解释:       HttpContext.Current.Cache:为当前 HTTP 请求获取Cache对象.       HttpRuntime.Cache:获取当前应用程序的C ...

  8. 缓存通用管理类 + 缓存 HttpContext.Current.Cache 和 HttpRuntime.Cache 的区别

    以前写asp.net时用HttpContext.Current.Cache存缓存很好用,今天写了一个windows服务程序,HttpContext.Current.Cache存缓存的时候还好,取的时候 ...

  9. 异步 HttpContext.Current实现取值的方法(解决异步Application,Session,Cache...等失效的问题)...

    在一个项目中,为了系统执行效率更快,把一个经常用到的数据库表通过dataset放到Application中,发现在异步实现中每一次都会出现HttpContext.Current为null的异常,后来在 ...

最新文章

  1. Ubuntu下 安装 window 虚拟机
  2. java memorycache原理_JVM代码缓存区CodeCache原理及用法解析
  3. java int字母,从Java中获取int,也包含字母
  4. LeetCode 559. N叉树的最大深度
  5. ChineseSemanticKB,面向中文处理的12类、百万规模的语义常用词库存
  6. 刷爆了!李彦宏:这类程序员我给100万!你怎么看?
  7. 机器学习-KMeans聚类 K值以及初始类簇中心点的选取
  8. Android四级缓存,RecyclerView的四级缓存-初探
  9. 谷歌弃用 APK 格式!替代品 AAB 有何优势?
  10. 中国光谷大数据产业联盟成立 打造大数据产业生态圈
  11. sap 双计量单位_[原创]浅谈MM模块的双计量单位(二)
  12. 隔壁宿舍的都哭了,单片机最小应用系统不懂你都毕不了业
  13. iOS 本地自动打包工具
  14. Raki的读paper小记:Star-Transformer
  15. 高职高专教材c语言,高职《C语言程序设计》教材建设研究
  16. pycharm 连接SQL
  17. 通信系统仿真原理与无线应用笔记-MATLAB
  18. 数据库学习与应用之什么是数据库
  19. 领扣LintCode算法问题答案-983. 棒球游戏
  20. 【SAR综述】复杂场景单通道SAR目标检测与鉴别方法

热门文章

  1. java中0x07_JAVA里0X00的表示
  2. 去除标题_你真的会写标题吗?企优托教您打造黄金标题离不开这三步
  3. gpedit msc组策略面板 win10在哪里_Win10家庭版找不到本地组策略gpedit.msc解决办法...
  4. debian 编译linux内核源码,Debian下为本机编译内核模块的方法
  5. unit类型是什么?_面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?...
  6. python生成器函数(generator),python3学习笔记:生成器generator
  7. oracle 如何形成死锁,Oracle数据表中的死锁情况解决方法
  8. cron 每10分钟执行一次_早餐儿子最爱它,简单卷一卷,10分钟做一大盘,三天两头吃一次...
  9. 在 Windows 命令提示符下启动 MySQL:net start mysql 发生系统错误 5。 拒绝访问。解决方式小结
  10. html+css 小案例(一)