HttpContext.Current:异步模式下的疑似陷阱之源
最近园子里首页有好几篇文章都是讲异步编程的,尤其是几篇讲博客园自身的异步化建设的文章,看了以后很有收获。
闲暇之余再重新查查资料温故知新学习一遍,重新认识了SynchronizationContext、AspNetSynchronizationContext和ConfigureAwait。
最大的心得是,web异步化处理后,容易引发问题的一个重要方面就是请求上下文,也就是本文标题里的HttpContext.Current。
园子里fish-li写过一篇HttpContext.Current并不是无处不在,写的比较详细深入,看过这篇文章你就会非常明确用了HttpContext.Current容易引发哪些问题了。
记得很早以前开发某项目,引入了一个外部日志组件,反汇编之后竟然发现有直接通过HttpContext.Current获取IP、UserAgent、请求参数等信息的,当时就对同事说千万不要在异步逻辑里调用这个组件里的任何记录日志的方法,防止触雷。
我的观点是,不要轻易在任何地方(类库)使用HttpContext.Current,因为它并非无处不在,尽量把HttpContext的当前请求对象保留起来,可以传参或者供外部类库回调时重新获取请求上下文使用。
但是,很多类库(包括MS自己的)的现有内部实现中都离不开HttpContext.Current,我这里并不是说类库中充斥着HttpContext.Current就是一种bad design。根据我个人的分析,至少目前已被广泛使用的FormsAutentication内部实现,满满的都是HttpContext.Current充斥其中,而且最核心的读写cookie的方法都依赖HttpContext.Current。如果完全适应各种异步场景,说不定也会碰到HttpContext.Current不灵的情况,目测还有可优化的空间^_^。
我们所熟悉的aspx,ascx,ashx,masterpage,MvcHandler,MvcRouteHandler和MvcHttpHandler等等,每一个类实现的背后都有Httpcontext的存在,是否也有HttpContext.Current这种暴力写法?据我所知,反正Page类是有的。好奇查看了一下MVC3的源码,搜索关键字“HttpContext.Current”,整个MVC3源码匹配的行数为12行,MvcHandler和MvcHttpHandler确实有HttpContext.Current的出现,它最终作为ProcessRequest或BeginProcessRequest方法的内部逻辑的一部分或者当中的参数,我们还是能够理解的。
参考:
http://www.cnblogs.com/cmt/p/configure_await_false.html
http://www.cnblogs.com/jesse2013/p/Asynchronous-Programming-In-DotNet.html
http://www.cnblogs.com/fish-li/archive/2013/04/06/3002940.html
http://msdn.microsoft.com/zh-cn/magazine/jj991977.aspx
http://msdn.microsoft.com/en-us/magazine/gg598924.aspx
附:在FormsAuthentication的SignOut方法中设置cookie过期时间的故事
先看SignOut方法的代码:

SignOut /// <summary>
/// Removes the forms-authentication ticket from the browser.
/// </summary>
public static void SignOut()
{
FormsAuthentication.Initialize();
HttpContext current = HttpContext.Current;
bool flag = current.CookielessHelper.DoesCookieValueExistInOriginal('F');
// Always clear the uri-cookie
current.CookielessHelper.SetCookieValue('F', null);
if (!CookielessHelperClass.UseCookieless(current, false, FormsAuthentication.CookieMode) || current.Request.Browser.Cookies)
{
string value = string.Empty;
if (current.Request.Browser["supportsEmptyStringInCookieValue"] == "false")
{
value = "NoCookie";
}
HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, value);
httpCookie.HttpOnly = true;
httpCookie.Path = FormsAuthentication._FormsCookiePath;
//What's the significance of Oct 12 1999
httpCookie.Expires = new DateTime(1999, 10, 12);
httpCookie.Secure = FormsAuthentication._RequireSSL;
if (FormsAuthentication._CookieDomain != null)
{
httpCookie.Domain = FormsAuthentication._CookieDomain;
}
current.Response.Cookies.RemoveCookie(FormsAuthentication.FormsCookieName);
current.Response.Cookies.Add(httpCookie);
}
if (flag)
{
current.Response.Redirect(FormsAuthentication.GetLoginPage(null), false);
}
}
注意设置过期时间httpCookie.Expires = new DateTime(1999, 10, 12);这一行,是不是很好奇想问为什么设置为1999年10月12号?设置过期时间的方式有多种,为什么写死这个魔幻时间,这个魔幻时间从哪里来的?
其实早在数年前就有人在stackoverflow上问过这个问题,“What's the significance of Oct 12 1999?”。
只要抛出问题,世上热心的好汉何其多哉,能准确回答的,不能确切回答的,还有小道消息道听途说的……
目前该问题已经关闭,共有12个可选答案,其中不乏有大神Scott Hanselman的回答,但最被推崇的竟然是排在Scott Hanselman后的那个说法,讲的煞有介事头头是道,就看你信哪个了。
我的另一最大收获是,原来NBA传奇球星张伯伦大帅卒于1999年10月12号。
参考:http://stackoverflow.com/questions/701030/whats-the-significance-of-oct-12-1999
HttpContext.Current:异步模式下的疑似陷阱之源的更多相关文章
- SQL Server AlwaysON 同步模式的疑似陷阱
原文:SQL Server AlwaysON 同步模式的疑似陷阱 SQL Server 2012 推出的最重要的功能之一Alwayson,是一个集之前Cluster和Mirror于一体的新功能,即解决 ...
- 业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份
业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份 WinForm酒店管理软件--框架这篇随笔可以说是我写的最被大家争议的随笔,一度是支持和反对是一样的多.大家对我做的这个行业 ...
- Log4j2异步情况下怎么防止丢日志的源码分析以及队列等待和拒绝策略分析
org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor以下所有源码均在此类中首先我们看下log4j2异步队列的初始化 从这里面我们 ...
- Ansible系列(七):执行过程分析、异步模式和速度优化
本文目录:1.1 ansible执行过程分析1.2 ansible并发和异步1.3 ansible的-t选项妙用1.4 优化ansible速度 1.4.1 设置ansible开启ssh长连接 1.4. ...
- ASP.NET多线程下使用HttpContext.Current为null解决方案
多线程或者异步调用中如何访问HttpContext? 前面我还提到在APM模式下的异步完成回调时,访问HttpContext.Current也会返回null,那么此时该怎么办呢? 答案有二种:1. 在 ...
- 异步 HttpContext.Current 为空null 另一种解决方法
1.场景 在导入通讯录过程中,把导入的失败.成功的号码数进行统计,然后保存到session中,客户端通过轮询显示状态. 在实现过程中,使用的async调用方法,出现HttpContext.Curren ...
- 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,解决办 ...
- ASP.NET多线程下使用HttpContext.Current
本来要实现asp.net下使用tcp通讯方式向服务器获取数据,开始采用的方式是 参考: ASP.NET多线程下使用HttpContext.Current为null解决方案 http://www.cnb ...
随机推荐
- ios6 滤镜相关知识内容网址---摘要
http://blog.csdn.net/justinjing0612/article/details/8145607#
- 11.APP打包成ipa文件,然后利用Application Loader 上架
第一步:保证已经完成了证书,Bundle Identifier 和描述文件的配置(未完成参考http://www.jianshu.com/p/391f6102b4fb) 第二步:打开要上传的项目,选择 ...
- Kinect2 随记
2016.03.30 calibration工作: 地板砖1.24m一格,大概走到2.5m时5*7的pattern开始无法检测到. 20种板上位姿*20种黑板位姿=400幅图像. 距离越远,水平角能检 ...
- 如何获取URL中的参数
获取URL中的某个参数或者所有参数以便我们后续去修改这个地址,在程序中是非常必要的.网上有很多这样的代码片段,为了以后查阅方便,顺便整理思路,下面使用2种方法来获取URL中的某个参数. 方法一 ,sp ...
- 1014 : Trie树 hihocoder
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. ...
- NOI 4976:硬币
描述 宇航员Bob有一天来到火星上,他有收集硬币的习惯.于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面值分别为a1,a2- an. Bob在机场看到了一个特别喜欢的礼物,想买来 ...
- java基础5_数组
一 数组是一个多个相同数据的集合.数组的长度一旦定义,将不能改变.数组的下标是从0开始的,到数组的长度-1结束. 1.数组的声明,初始化 int[] a = new int[3]{1,2,3}; in ...
- Java程序性能优化技巧
Java程序性能优化技巧 多线程.集合.网络编程.内存优化.缓冲..spring.设计模式.软件工程.编程思想 1.生成对象时,合理分配空间和大小new ArrayList(100); 2.优化for ...
- c1ctf2016 wp
web: 1.web萌新福利 没啥好说的,右键查看源码得key 2.you are not admin 一看题目,就想到http头修改,常见的x-forwarded-for,referer,host, ...
- SSH框架的简单示例(执行流程)
本文转自一篇博文,感觉通俗易懂,适用于初学j2ee者,与大家一起分享 (一)struts框架部分 1.打开Myeclipse,创建一个web project,项目名称为TestSSH. 2.在web的 ...