zoukankan      html  css  js  c++  java
  • 异步 HttpContext.Current 为空null 另一种解决方法

    1、场景

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

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

    image

    2、网络解答

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

    1、更改web.config配置文件

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

        image

    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 == 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,如下图:

    image

  • 相关阅读:
    IntellJ IDEA快捷键
    【Java基础】Java 增强型的for循环 for each
    Markdown简易入门
    kafka性能调优
    百度地图 libBaiduMapSDK_base_v4_2_1.so" is 32-bit instead of 64-bit错误
    centos7防火墙firewalld拒绝某ip或者某ip段访问服务器任何服务
    华为策略路由配置
    Windows Server 2012 R2 英文版安装中文语言包教程更改为中文版
    linux修改网卡名为eth0
    华为路由配置IPSec
  • 原文地址:https://www.cnblogs.com/zsy/p/5935516.html
Copyright © 2011-2022 走看看