asp.net mvc中在使用async的时候HttpContext为null的问题

摘要

HttpContext上下文并不是无处不在的。详情可以看下Fish Li的文章,解释的比较清楚。

HttpContext.Current并非无处不在

问题复现

        public async Task<ActionResult> Home()
        {
            return await Task.Factory.StartNew(() =>
            {
                var context = System.Web.HttpContext.Current;
                System.Web.HttpContext context2 = System.Runtime.Remoting.Messaging.CallContext.HostContext as HttpContext;
                return View();
            });
        }

比如有上面一段代码,你需要用到HttpContext,大部分人都会通过HttpContext.Current方式拿到当前请求的上下文。

但是

为什么拿不到上下文对象呢?

首先我们需要了解,HttpContext保存在哪儿?,在Fish Li的文章中已经说的很详细了,HttpContext其实是保存在CallContext.HostContext这个属性中的。

CallContext.HostContext

获取或设置与当前线程相关联的主机上下文。(MSDN)

当前线程: 当前线程是指与【当前请求】相关的线程。

其中Fish Li有这么段话解释的比较清楚

【当前线程】是个什么意思? 我为什么要突出这个词呢?

答:
1. 当前线程是指与【当前请求】相关的线程。
2. 在ASP.NET中,有些线程并非总是与请求相关。

感觉有点绕口吗? 不容易理解吗? 还是继续往下看吧。

虽然在ASP.NET程序中,几乎所有的线程都应该是为响应请求而运行的,
但是,还有一些线程却不是为了响应请求而运行,例如:
1. 定时器的回调。
2. Cache的移除通知。
3. APM模式下异步完成回调。
4. 主动创建线程或者将任务交给线程池来执行。

在以上这些情况中,如果线程执行到HttpContext.Current,您认为会返回什么?
还是一个HttpContext的实例引用吗?
如何是,那它与哪个请求关联?

显然,在1,2二种情况中,访问HttpContext.Current将会返回 null 。
因为很有可能任务在运行时根本没有任何请求发生。
了解异步的人应该能很容易理解第3种情况(就当是个结论吧)
第4种情况就更不需要解释了,因为确实不是当前线程。

猜测,task.factory.startnew,开启一个新的任务执行的。所以这里拿不到HttpContext也符合上述的情况。

那么我们可以在请求开始的时候可以通过变量将上下文保存起来,比如下面的方式。

总结

通过本篇文章,在异步中使用HttpContext.Current需要特别注意,它并不是无处不在的,所以在使用的时候,最好判断一下是否为null。

相关文章

Fish Li:HttpContext.Current并非无处不在

时间: 2024-10-10 12:22:31

asp.net mvc中在使用async的时候HttpContext为null的问题的相关文章

ASP.NET MVC中使用异步控制器

线程池 一直想把项目改写成异步,但是ASP.NETMVC3下写的过于繁琐,.NET 4.5与ASP.NET MVC下代码写起来就比较简单了, MS好像也一直喜欢这样搞,每一个成熟的东西,都要演变好几个版本,才能趋于规范. ASP.NET MVC 中为什么需要使用异步呢,IIS有一个线程池来处理用户的请求,当一个新的请求过来时,将调度池中的线程以处理该请求,然而,但并发量很高的情况下,池中的线程已经不能够满足这么多的请求时候,池中的每一个线程都处于忙的状态则在处理请求时将阻塞处理请求的线程,并且该

Asp.NET MVC 中使用 SignalR 实现推送功能

一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息. 可访问其官方网站:https://github.com/SignalR/ 获取更多资讯. 二.Asp.net SignalR 是个什么东东 Asp.net SignalR是微软为实现实时通信的一个类库.一般情况下,SignalR会使用JavaScript的长轮询(lo

在 ASP.NET MVC 中使用异步控制器

线程池 一直想把项目改写成异步,但是ASP.NETMVC3下写的过于繁琐,.NET 4.5与ASP.NET MVC下代码写起来就比较简单了, MS好像也一直喜欢这样搞,每一个成熟的东西,都要演变好几个版本,才能趋于规范. ASP.NET MVC 中为什么需要使用异步呢,IIS有一个线程池来处理用户的请求,当一个新的请求过来时,将调度池中的线程以处理该请求,然而,但并发量很高的情况下,池中的线程已经不能够满足这么多的请求时候,池中的每一个线程都处于忙的状态则在处理请求时将阻塞处理请求的线程,并且该

ASP.NET MVC中商品模块小样

在前面的几篇文章中,已经在控制台和界面实现了属性值的笛卡尔乘积,这是商品模块中的一个难点.本篇就来实现在ASP.NET MVC4下商品模块的一个小样.与本篇相关的文章包括: 1.ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积01, 在控制台实现  2.ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现   3.再议ASP.NET MVC中CheckBoxList的验证   4.ASP.NET MVC在服务端把异步上传的图片裁剪成不同尺寸分别保存,并设置上

log4net 使用总结- (2)在ASP.NET MVC 中使用

log4net在ASP.NET MVC中的配置,还有一种配置方式,即不在web.config中,而是单独新建一个log4net.config 在根目录下 第一.引用log4net.dll 第二.在站点根目录下增加log4net.config <?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="

ASP.NET MVC中使用ASP.NET AJAX异步访问WebService

使用过ASP.NET AJAX的朋友都知道,怎么通过ASP.NET AJAX在客户端访问WebService,其实在ASP.NET MVC中使用ASP.NET AJAX异步访问WebService 也没什么大的差别. 在ASP.NET应用程序里使用ASP.NET AJAX访问WebService通常都是通过ScriptMananger引入WebService生成客户端代理的方法,同时也可以使用Microsoft Ajax Library来完成.本文将介绍在ASP.NET MVC中使用ASP.NE

ASP.NET MVC中使用FluentValidation验证实体

1.FluentValidation介绍 FluentValidation是与ASP.NET DataAnnotataion Attribute验证实体不同的数据验证组件,提供了将实体与验证分离开来的验证方式,同时FluentValidation还提供了表达式链式语法. 2.安装FluentValidation FluentValidation地址:http://fluentvalidation.codeplex.com/ 使用Visual Studio的管理NuGet程序包安装FluentVa

ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器

ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器一:闲谈一下:1.现在任务跟踪管理系统已经开发快要结束了,抽一点时间来写一下,想一想自己就有成就感啊!!  2.关于任务跟踪管理系统项目中遇到的Windows服务以及Webservice的综合应用的问题. 大家好这是我第二次写博客 ,写的不好请大家多多谅解, 希望大家可以多多指正. 二:我稍微的整理了一下关于这个分布式定时器需求:1.根据任务跟踪管理系统中的数据库的AnswerSheet 表格中找到客户编

Asp.Net MVC中DropDownListFor的用法(转)

2016.03.04 扩展:如果 view中传入的是List<T>类型 怎么使用 DropList 既然是List<T> 那么我转化成 T  List<T>的第一个,最后一个不就是M吗? @Html.DropDownListFor(model=>model.First().Title, ViewData["Title"] as List<SelectListItem>, "标题", @"dropdown