private static void OnScheduledWork(object state) { Scheduler thisPtr = (Scheduler)state; // We snapshot these values here so that we can // use them after calling OnSchedulerIdle. //bool isTracingEnabled = FxTrace.Trace.ShouldTraceToTraceSource(TraceEventLevel.Informational); Guid oldActivityId = Guid.Empty; Guid workflowInstanceId = Guid.Empty; //if (isTracingEnabled) //{ // oldActivityId = DiagnosticTraceBase.ActivityId; // workflowInstanceId = thisPtr.callbacks.WorkflowInstanceId; // FxTrace.Trace.SetAndTraceTransfer(workflowInstanceId, true); // if (thisPtr.resumeTraceRequired) // { // if (TD.WorkflowActivityResumeIsEnabled()) // { // TD.WorkflowActivityResume(workflowInstanceId); // } // } //} thisPtr.callbacks.ThreadAcquired(); RequestedAction nextAction = continueAction; bool idleOrPaused = false; while (object.ReferenceEquals(nextAction, continueAction)) { if (thisPtr.IsIdle || thisPtr.isPausing) { idleOrPaused = true; break; } // cycle through (queue->thisPtr.firstWorkItem->currentWorkItem) WorkItem currentWorkItem = thisPtr.firstWorkItem; // promote an item out of our work queue if necessary if (thisPtr.workItemQueue != null && thisPtr.workItemQueue.Count > 0) { thisPtr.firstWorkItem = thisPtr.workItemQueue.Dequeue(); } else { thisPtr.firstWorkItem = null; } if (TD.ExecuteWorkItemStartIsEnabled()) { TD.ExecuteWorkItemStart(); } nextAction = thisPtr.callbacks.ExecuteWorkItem(currentWorkItem); if (TD.ExecuteWorkItemStopIsEnabled()) { TD.ExecuteWorkItemStop(); } } //bool notifiedCompletion = false; //bool isInstanceComplete = false; if (idleOrPaused || object.ReferenceEquals(nextAction, abortAction)) { thisPtr.isPausing = false; thisPtr.isRunning = false; thisPtr.NotifyWorkCompletion(); //notifiedCompletion = true; //if (isTracingEnabled) //{ // isInstanceComplete = thisPtr.callbacks.IsCompleted; //} // After calling SchedulerIdle we no longer have the lock. That means // that any subsequent processing in this method won't have the single // threaded guarantee. thisPtr.callbacks.SchedulerIdle(); } else if (!object.ReferenceEquals(nextAction, yieldSilentlyAction)) { Fx.Assert(nextAction is NotifyUnhandledExceptionAction, "This is the only other option"); NotifyUnhandledExceptionAction notifyAction = (NotifyUnhandledExceptionAction)nextAction; // We only set isRunning back to false so that the host doesn't // have to treat this like a pause notification. As an example, // a host could turn around and call run again in response to // UnhandledException without having to go through its operation // dispatch loop first (or request pause again). If we reset // isPausing here then any outstanding operations wouldn't get // signaled with that type of host. thisPtr.isRunning = false; thisPtr.NotifyWorkCompletion(); //notifiedCompletion = true; //if (isTracingEnabled) //{ // isInstanceComplete = thisPtr.callbacks.IsCompleted; //} thisPtr.callbacks.NotifyUnhandledException(notifyAction.Exception, notifyAction.Source); } //if (isTracingEnabled) //{ // if (notifiedCompletion) // { // if (isInstanceComplete) // { // if (TD.WorkflowActivityStopIsEnabled()) // { // TD.WorkflowActivityStop(workflowInstanceId); // } // } // else // { // if (TD.WorkflowActivitySuspendIsEnabled()) // { // TD.WorkflowActivitySuspend(workflowInstanceId); // } // } // } // DiagnosticTraceBase.ActivityId = oldActivityId; //} }
private static void OnScheduledWork(object state) { Scheduler scheduler = (Scheduler)state; bool flag = FxTrace.Trace.ShouldTraceToTraceSource(TraceEventLevel.Informational); Guid empty = Guid.Empty; Guid newId = Guid.Empty; if (flag) { empty = DiagnosticTrace.ActivityId; newId = scheduler.callbacks.WorkflowInstanceId; FxTrace.Trace.SetAndTraceTransfer(newId, true); if (scheduler.resumeTraceRequired && TD.WorkflowActivityResumeIsEnabled()) { TD.WorkflowActivityResume(newId.ToString()); } } scheduler.callbacks.ThreadAcquired(); RequestedAction continueAction = Scheduler.continueAction; bool flag2 = false; while (object.ReferenceEquals(continueAction, Scheduler.continueAction)) { if (scheduler.IsIdle || scheduler.isPausing) { flag2 = true; break; } System.Activities.Runtime.WorkItem firstWorkItem = scheduler.firstWorkItem; if ((scheduler.workItemQueue != null) && (scheduler.workItemQueue.Count > 0)) { scheduler.firstWorkItem = scheduler.workItemQueue.Dequeue(); } else { scheduler.firstWorkItem = null; } continueAction = scheduler.callbacks.ExecuteWorkItem(firstWorkItem); } bool flag3 = false; bool isCompleted = false; if (flag2 || object.ReferenceEquals(continueAction, abortAction)) { scheduler.isPausing = false; scheduler.isRunning = false; scheduler.NotifyWorkCompletion(); flag3 = true; if (flag) { isCompleted = scheduler.callbacks.IsCompleted; } scheduler.callbacks.SchedulerIdle(); } else if (!object.ReferenceEquals(continueAction, yieldSilentlyAction)) { NotifyUnhandledExceptionAction action2 = (NotifyUnhandledExceptionAction)continueAction; scheduler.isRunning = false; scheduler.NotifyWorkCompletion(); flag3 = true; if (flag) { isCompleted = scheduler.callbacks.IsCompleted; } scheduler.callbacks.NotifyUnhandledException(action2.Exception, action2.Source); } if (flag) { if (flag3) { if (isCompleted) { if (TD.WorkflowActivityStopIsEnabled()) { TD.WorkflowActivityStop(newId.ToString()); } } else if (TD.WorkflowActivitySuspendIsEnabled()) { TD.WorkflowActivitySuspend(newId.ToString()); } } DiagnosticTrace.ActivityId = empty; } }
// This method should only be called when we relinquished the thread but did not // complete the operation (silent yield is the current example) public void InternalResume(RequestedAction action) { Fx.Assert(this.isRunning, "We should still be processing work - we just don't have a thread"); bool isTracingEnabled = FxTrace.ShouldTraceInformation; bool notifiedCompletion = false; bool isInstanceComplete = false; if (this.callbacks.IsAbortPending) { this.isPausing = false; this.isRunning = false; this.NotifyWorkCompletion(); notifiedCompletion = true; if (isTracingEnabled) { isInstanceComplete = this.callbacks.IsCompleted; } // After calling SchedulerIdle we no longer have the lock. That means // that any subsequent processing in this method won't have the single // threaded guarantee. this.callbacks.SchedulerIdle(); } else if (object.ReferenceEquals(action, continueAction)) { ScheduleWork(false); } else { Fx.Assert(action is NotifyUnhandledExceptionAction, "This is the only other choice because we should never have YieldSilently here"); NotifyUnhandledExceptionAction notifyAction = (NotifyUnhandledExceptionAction)action; // We only set isRunning back to false so that the host doesn't // have to treat this like a pause notification. As an example, // a host could turn around and call run again in response to // UnhandledException without having to go through its operation // dispatch loop first (or request pause again). If we reset // isPausing here then any outstanding operations wouldn't get // signaled with that type of host. this.isRunning = false; this.NotifyWorkCompletion(); notifiedCompletion = true; if (isTracingEnabled) { isInstanceComplete = this.callbacks.IsCompleted; } this.callbacks.NotifyUnhandledException(notifyAction.Exception, notifyAction.Source); } if (isTracingEnabled) { if (notifiedCompletion) { Guid oldActivityId = Guid.Empty; bool resetId = false; if (isInstanceComplete) { if (TD.WorkflowActivityStopIsEnabled()) { oldActivityId = WfEventSource.CurrentThreadActivityId; WfEventSource.SetCurrentThreadActivityId(this.callbacks.WorkflowInstanceId); resetId = true; TD.WorkflowActivityStop(this.callbacks.WorkflowInstanceId); } } else { if (TD.WorkflowActivitySuspendIsEnabled()) { oldActivityId = WfEventSource.CurrentThreadActivityId; WfEventSource.SetCurrentThreadActivityId(this.callbacks.WorkflowInstanceId); resetId = true; TD.WorkflowActivitySuspend(this.callbacks.WorkflowInstanceId); } } if (resetId) { WfEventSource.SetCurrentThreadActivityId(oldActivityId); } } } }
public void InternalResume(RequestedAction action) { bool shouldTraceInformation = FxTrace.ShouldTraceInformation; bool flag2 = false; bool isCompleted = false; if (this.callbacks.IsAbortPending) { this.isPausing = false; this.isRunning = false; this.NotifyWorkCompletion(); flag2 = true; if (shouldTraceInformation) { isCompleted = this.callbacks.IsCompleted; } this.callbacks.SchedulerIdle(); } else if (object.ReferenceEquals(action, continueAction)) { this.ScheduleWork(false); } else { NotifyUnhandledExceptionAction action2 = (NotifyUnhandledExceptionAction)action; this.isRunning = false; this.NotifyWorkCompletion(); flag2 = true; if (shouldTraceInformation) { isCompleted = this.callbacks.IsCompleted; } this.callbacks.NotifyUnhandledException(action2.Exception, action2.Source); } if (shouldTraceInformation && flag2) { Guid empty = Guid.Empty; bool flag4 = false; if (isCompleted) { if (TD.WorkflowActivityStopIsEnabled()) { empty = DiagnosticTrace.ActivityId; DiagnosticTrace.ActivityId = this.callbacks.WorkflowInstanceId; flag4 = true; TD.WorkflowActivityStop(this.callbacks.WorkflowInstanceId.ToString()); } } else if (TD.WorkflowActivitySuspendIsEnabled()) { empty = DiagnosticTrace.ActivityId; DiagnosticTrace.ActivityId = this.callbacks.WorkflowInstanceId; flag4 = true; TD.WorkflowActivitySuspend(this.callbacks.WorkflowInstanceId.ToString()); } if (flag4) { DiagnosticTrace.ActivityId = empty; } } }