文章出處

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


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()