using System; using System.Diagnostics; using System.Threading; using System.Reflection; using System.Web; using System.Runtime.Remoting.Messaging; namespace Amib.Threading { #region CallerThreadContext class /// <summary> /// This class stores the caller call context in order to restore /// it when the work item is executed in the thread pool environment. /// </summary> internal class CallerThreadContext { #region Prepare reflection information // Cached type information. private static MethodInfo getLogicalCallContextMethodInfo = typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo setLogicalCallContextMethodInfo = typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); private static string HttpContextSlotName = GetHttpContextSlotName(); private static string GetHttpContextSlotName() { FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); if( fi != null ) return (string)fi.GetValue(null); else // Use the default "HttpContext" slot name return "HttpContext"; } #endregion #region Private fields private HttpContext _httpContext = null; private LogicalCallContext _callContext = null; #endregion /// <summary> /// Constructor /// </summary> private CallerThreadContext() { } public bool CapturedCallContext { get { return (null != _callContext); } } public bool CapturedHttpContext { get { return (null != _httpContext); } } /// <summary> /// Captures the current thread context /// </summary> /// <returns></returns> public static CallerThreadContext Capture( bool captureCallContext, bool captureHttpContext) { Debug.Assert(captureCallContext || captureHttpContext); CallerThreadContext callerThreadContext = new CallerThreadContext(); // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() // Capture Call Context if(captureCallContext && (getLogicalCallContextMethodInfo != null)) { callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null); if (callerThreadContext._callContext != null) { callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); } } // Capture httpContext if (captureHttpContext && (null != HttpContext.Current)) { callerThreadContext._httpContext = HttpContext.Current; } return callerThreadContext; } /// <summary> /// Applies the thread context stored earlier /// </summary> /// <param name="callerThreadContext"></param> public static void Apply(CallerThreadContext callerThreadContext) { if (null == callerThreadContext) { throw new ArgumentNullException("callerThreadContext"); } // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() // Restore call context if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) { setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); } // Restore HttpContext if (callerThreadContext._httpContext != null) { CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); } } } #endregion } /* // Ami Bar // amibar@gmail.com using System; using System.Threading; using System.Globalization; using System.Security.Principal; using System.Reflection; using System.Runtime.Remoting.Contexts; namespace Amib.Threading.Internal { #region CallerThreadContext class /// <summary> /// This class stores the caller thread context in order to restore /// it when the work item is executed in the context of the thread /// from the pool. /// Note that we can't store the thread's CompressedStack, because /// it throws a security exception /// </summary> public class CallerThreadContext { private CultureInfo _culture = null; private CultureInfo _cultureUI = null; private IPrincipal _principal; private System.Runtime.Remoting.Contexts.Context _context; private static FieldInfo _fieldInfo = GetFieldInfo(); private static FieldInfo GetFieldInfo() { Type threadType = typeof(Thread); return threadType.GetField( "m_Context", BindingFlags.Instance | BindingFlags.NonPublic); } /// <summary> /// Constructor /// </summary> private CallerThreadContext() { } /// <summary> /// Captures the current thread context /// </summary> /// <returns></returns> public static CallerThreadContext Capture() { CallerThreadContext callerThreadContext = new CallerThreadContext(); Thread thread = Thread.CurrentThread; callerThreadContext._culture = thread.CurrentCulture; callerThreadContext._cultureUI = thread.CurrentUICulture; callerThreadContext._principal = Thread.CurrentPrincipal; callerThreadContext._context = Thread.CurrentContext; return callerThreadContext; } /// <summary> /// Applies the thread context stored earlier /// </summary> /// <param name="callerThreadContext"></param> public static void Apply(CallerThreadContext callerThreadContext) { Thread thread = Thread.CurrentThread; thread.CurrentCulture = callerThreadContext._culture; thread.CurrentUICulture = callerThreadContext._cultureUI; Thread.CurrentPrincipal = callerThreadContext._principal; // Uncomment the following block to enable the Thread.CurrentThread /* if (null != _fieldInfo) { _fieldInfo.SetValue( Thread.CurrentThread, callerThreadContext._context); } * / } } #endregion } */