首页 > 代码库 > 异步 HttpContext.Current 为空null 另一种解决方法

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

1、场景

    在导入通讯录过程中,把导入的失败、成功的号码数进行统计,然后保存到session中,客户端通过轮询显示状态。

    在实现过程中,使用的async调用方法,出现HttpContext.Current为null的情况,如下:

技术分享

 

2、网络解答

    从百度与谷歌查询,分以下两种情况进行解答:

1、更改web.config配置文件

    Stackoverflow给出如下解决方案:http://stackoverflow.com/questions/18383923/why-is-httpcontext-current-null-after-await

    技术分享

2、缓存HttpContext

    博客地址:http://www.cnblogs.com/pokemon/p/5116446.html

    本博客,给出了异步下HttpContext.Current为空的原因分析。本文中的最后提取出如下方法:

using System;using System.Linq.Expressions;using System.Reflection;using System.Threading;using System.Web;namespace TxSms{    /// <summary>    /// 解决Asp.net Mvc中使用异步的时候HttpContext.Current为null的方法    /// <remarks>    /// http://www.cnblogs.com/pokemon/p/5116446.html    /// </remarks>    /// </summary>    public static class HttpContextHelper    {        /// <summary>        /// 在同步上下文中查找当前会话<see cref="System.Web.HttpContext" />对象        /// </summary>        /// <param name="context"></param>        /// <returns></returns>        public static HttpContext FindHttpContext(this SynchronizationContext context)        {            if (context == null)            {                return null;            }            var factory = GetFindApplicationDelegate(context);            return factory?.Invoke(context).Context;        }        private static Func<SynchronizationContext, HttpApplication> GetFindApplicationDelegate(SynchronizationContext context)        {            Delegate factory = null;            Type type = context.GetType();            if (!type.FullName.Equals("System.Web.LegacyAspNetSynchronizationContext"))            {                return null;            }            //找到字段            ParameterExpression sourceExpression = Expression.Parameter(typeof(SynchronizationContext), "context");            //目前支持 System.Web.LegacyAspNetSynchronizationContext 内部类            //查找        private HttpApplication _application 字段            Expression sourceInstance = Expression.Convert(sourceExpression, type);            FieldInfo applicationFieldInfo = type.GetField("_application", BindingFlags.NonPublic | BindingFlags.Instance);            Expression fieldExpression = Expression.Field(sourceInstance, applicationFieldInfo);            factory = Expression.Lambda<Func<SynchronizationContext, HttpApplication>>(fieldExpression, sourceExpression).Compile();            //返回委托            return ((Func<SynchronizationContext, HttpApplication>)factory);        }        /// <summary>        /// 确定异步状态的上下文可用        /// </summary>        /// <param name="context"></param>        /// <returns></returns>        public static HttpContext Check(this HttpContext context)        {            return context ?? (context = SynchronizationContext.Current.FindHttpContext());        }    }}

 

3、实现

    通过2对两种方法都进行尝试,发现还是不可用的。使用session共享数据行不通,换另外一种思路,使用cache,封装类库如下:

using System;using System.Collections;using System.Web;using System.Web.Caching;namespace TxSms{    /// <summary>    /// HttpRuntime Cache读取设置缓存信息封装    /// <auther>    ///     <name>Kencery</name>    ///     <date>2015-8-11</date>    /// </auther>    /// 使用描述:给缓存赋值使用HttpRuntimeCache.Set(key,value....)等参数(第三个参数可以传递文件的路径(HttpContext.Current.Server.MapPath()))    /// 读取缓存中的值使用JObject jObject=HttpRuntimeCache.Get(key) as JObject,读取到值之后就可以进行一系列判断    /// </summary>    public static class HttpRuntimeCache    {        /// <summary>        /// 设置缓存时间,配置(从配置文件中读取)        /// </summary>        private const double Seconds = 30 * 24 * 60 * 60;        /// <summary>        /// 缓存指定对象,设置缓存        /// </summary>        public static bool Set(string key, object value)        {            return Set(key, value, null, DateTime.Now.AddSeconds(Seconds), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);        }        /// <summary>        ///  缓存指定对象,设置缓存        /// </summary>        public static bool Set(string key, object value, string path)        {            try            {                var cacheDependency = new CacheDependency(path);                return Set(key, value, cacheDependency);            }            catch            {                return false;            }        }        /// <summary>        /// 缓存指定对象,设置缓存        /// </summary>        public static bool Set(string key, object value, CacheDependency cacheDependency)        {            return Set(key, value, cacheDependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);        }        /// <summary>        /// 缓存指定对象,设置缓存        /// </summary>        public static bool Set(string key, object value, double seconds, bool isAbsulute)        {            return Set(key, value, null, (isAbsulute ? DateTime.Now.AddSeconds(seconds) : Cache.NoAbsoluteExpiration),                (isAbsulute ? Cache.NoSlidingExpiration : TimeSpan.FromSeconds(seconds)), CacheItemPriority.Default, null);        }        /// <summary>        /// 获取缓存对象        /// </summary>        public static object Get(string key)        {            return GetPrivate(key);        }        /// <summary>        /// 判断缓存中是否含有缓存该键        /// </summary>        public static bool Exists(string key)        {            return (GetPrivate(key) != null);        }        /// <summary>        /// 移除缓存对象        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        public static bool Remove(string key)        {            if (string.IsNullOrEmpty(key))            {                return false;            }            HttpRuntime.Cache.Remove(key);            return true;        }        /// <summary>        /// 移除所有缓存        /// </summary>        /// <returns></returns>        public static bool RemoveAll()        {            IDictionaryEnumerator iDictionaryEnumerator = HttpRuntime.Cache.GetEnumerator();            while (iDictionaryEnumerator.MoveNext())            {                HttpRuntime.Cache.Remove(Convert.ToString(iDictionaryEnumerator.Key));            }            return true;        }        /// <summary>        /// 设置缓存        /// </summary>        public static bool Set(string key, object value, CacheDependency cacheDependency, DateTime dateTime,            TimeSpan timeSpan, CacheItemPriority cacheItemPriority, CacheItemRemovedCallback cacheItemRemovedCallback)        {            if (string.IsNullOrEmpty(key) || value =http://www.mamicode.com/= null)            {                return false;            }            HttpRuntime.Cache.Insert(key, value, cacheDependency, dateTime, timeSpan, cacheItemPriority, cacheItemRemovedCallback);            return true;        }        /// <summary>        /// 获取缓存        /// </summary>        private static object GetPrivate(string key)        {            return string.IsNullOrEmpty(key) ? null : HttpRuntime.Cache.Get(key);        }    }}

    在此调试,完全可以找到((ImportContactStateModel)model).SuccessNum,如下图:

技术分享

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