/// <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(); // 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"); } // Restore call context if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) { setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); } // Restore HttpContext if (callerThreadContext._httpContext != null) { HttpContext.Current = callerThreadContext._httpContext; //CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); } }
/// <summary> /// Initialize the callback holding object. /// </summary> /// <param name="workItemsGroup">The workItemGroup of the workitem</param> /// <param name="workItemInfo">The WorkItemInfo of te workitem</param> /// <param name="callback">Callback delegate for the callback.</param> /// <param name="state">State with which to call the callback delegate.</param> /// /// We assume that the WorkItem object is created within the thread /// that meant to run the callback public WorkItem( IWorkItemsGroup workItemsGroup, WorkItemInfo workItemInfo, WorkItemCallback callback, object state) { _workItemsGroup = workItemsGroup; _workItemInfo = workItemInfo; #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext) { _callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext); } #endif _callback = callback; _state = state; _workItemResult = new WorkItemResult(this); Initialize(); }
/// <summary> /// Execute the work item /// </summary> private void ExecuteWorkItem() { #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) CallerThreadContext ctc = null; if (null != _callerContext) { ctc = CallerThreadContext.Capture(_callerContext.CapturedCallContext, _callerContext.CapturedHttpContext); CallerThreadContext.Apply(_callerContext); } #endif Exception exception = null; object result = null; try { try { result = _callback(_state); } catch (Exception e) { // Save the exception so we can rethrow it later exception = e; } // Remove the value of the execution thread, so it will be impossible to cancel the work item, // since it is already completed. // Cancelling a work item that already completed may cause the abortion of the next work item!!! Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread); if (null == executionThread) { // Oops! we are going to be aborted..., Wait here so we can catch the ThreadAbortException Thread.Sleep(60 * 1000); // If after 1 minute this thread was not aborted then let it continue working. } } // We must treat the ThreadAbortException or else it will be stored in the exception variable catch (ThreadAbortException tae) { tae.GetHashCode(); // Check if the work item was cancelled // If we got a ThreadAbortException and the STP is not shutting down, it means the // work items was cancelled. if (!SmartThreadPool.CurrentThreadEntry.AssociatedSmartThreadPool.IsShuttingdown) { #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) Thread.ResetAbort(); #endif } } #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) if (null != _callerContext) { CallerThreadContext.Apply(ctc); } #endif if (!SmartThreadPool.IsWorkItemCanceled) { SetResult(result, exception); } }
/// <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(); // 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; }