/// <summary> /// The do spin. /// </summary> /// <param name="loops"> /// The loops. /// </param> /// <param name="iterations"> /// The iterations. /// </param> /// <param name="notify"> /// The notify. /// </param> /// <param name="token"> /// The token. /// </param> public void DoSpin(int loops, int iterations, SpinNotify notify, CancellationToken token) { for (var i = 0; i < loops; i++) { WorkflowTrace.Verbose("TaskSpinWaiter loop {0} of {1}", i, loops); try { if (token.IsCancellationRequested) { WorkflowTrace.Verbose("TaskSpinWaiter Cancel Requested"); return; } Task.Run( () => { WorkflowTrace.Verbose("SpinWait({0})", iterations); Thread.SpinWait(iterations); if (token.IsCancellationRequested) { WorkflowTrace.Verbose("SpinWait - Cancellation is requested"); } }, token).Wait(); } finally { notify.LoopComplete(loops, iterations); } } WorkflowTrace.Verbose("TaskSpinWaiter done with {0} iterations", iterations * loops); }
public void CancelWorkflowApp() { // Arrange TestTrace.Arrange(); var spinExecuting = new AutoResetEvent(false); var completed = new AutoResetEvent(false); var notify = new SpinNotify { LoopComplete = (loops, iterations) => spinExecuting.Set() }; var activity = CreateSequenceWithSpinWaiter(typeof(SpinWaiter)); WorkflowApplicationCompletedEventArgs completedArgs = null; var workflowApplication = new WorkflowApplication(activity) { Completed = args => { completedArgs = args; WorkflowTrace.Verbose( "Completed state: {0} fault {1}", args.CompletionState, args.TerminationException); completed.Set(); }, Aborted = args => WorkflowTrace.Verbose("Aborted {0}", args.Reason), }; var source = new CancellationTokenSource(Constants.Timeout); var tracking = new ListTrackingParticipant(); workflowApplication.Extensions.Add(tracking); workflowApplication.Extensions.Add(notify); var activitySource = new ActivityCancellationToken(source.Token); workflowApplication.Extensions.Add(activitySource); try { // Act TestTrace.Act(); workflowApplication.Run(); TestTrace.Write("Waiting for AsyncSpinWaiter to start executing"); var spinWait = spinExecuting.WaitOne(TimeSpan.FromSeconds(10)); if (spinWait) { source.Token.Register(workflowApplication.Cancel); TestTrace.Write("Cancelling workflow"); source.Cancel(); // workflow.Cancel(); } else { TestTrace.Write("spinWait timeout"); } var isComplete = completed.WaitOne(Constants.Timeout); // Assert TestTrace.Assert(); Assert.IsTrue(isComplete); Assert.IsNotNull(completedArgs); Assert.AreEqual(ActivityInstanceState.Canceled, completedArgs.CompletionState); } finally { TestTrace.Finally(); tracking.Trace(); } }
public void CancelTaskAsyncActivityViaToken() { // Arrange TestTrace.Arrange(); var spinExecuting = new ManualResetEvent(false); var completedEvent = new ManualResetEvent(false); var notify = new SpinNotify { LoopComplete = (loops, iterations) => spinExecuting.Set() }; var cancellationHandlerClosed = new AutoResetEvent(false); var activity = CreateSequenceWithSpinWaiter(typeof(TaskSpinWaiter)); var tracking = new ListTrackingParticipant(); var workflow = new WorkflowP1(activity) { Timeout = Constants.Timeout, Extensions = { tracking, notify } }; workflow.When.Activity.Name("CancellationHandler").Closed += (sender, args) => cancellationHandlerClosed.Set(); workflow.When.Completed += (sender, args) => completedEvent.Set(); var source = new CancellationTokenSource(Constants.Timeout); try { // Act TestTrace.Act(); var task = workflow.RunAsync(source.Token); TestTrace.Write("Waiting for AsyncSpinWaiter to start executing"); Assert.IsTrue(spinExecuting.WaitOne(Constants.Timeout)); TestTrace.Write("Cancelling workflow with token"); source.Cancel(); TestTrace.Write("Waiting for workflow to execute cancellation handler"); Assert.IsTrue(cancellationHandlerClosed.WaitOne(Constants.Timeout)); TestTrace.Write("Waiting for workflow"); // Assert TestTrace.Assert(); AssertHelper.Throws<AggregateException>(task.Wait, typeof(TaskCanceledException)); Assert.IsTrue( tracking.Records.Any(ActivityInstanceState.Closed, "CancellationHandler"), "The cancellation handler was not invoked"); Assert.IsTrue(task.IsCanceled); Assert.IsTrue(task.IsCompleted); } finally { TestTrace.Finally(); workflow.Trace(); } }
public void CancelWithAsyncActivityWillCancel() { // Arrange TestTrace.Arrange(); var spinExecuting = new AutoResetEvent(false); var notify = new SpinNotify { LoopComplete = (loops, iterations) => spinExecuting.Set() }; var cancellationHandlerClosed = new AutoResetEvent(false); var activity = CreateSequenceWithSpinWaiter(typeof(AsyncSpinWaiter)); var tracking = new ListTrackingParticipant(); var workflow = new WorkflowP1(activity) { Timeout = Constants.Timeout, Extensions = { tracking, notify } }; workflow.When.Activity.Name("CancellationHandler").Closed += (sender, args) => cancellationHandlerClosed.Set(); var source = new CancellationTokenSource(Constants.Timeout); try { // Act TestTrace.Act(); workflow.Until.Idle.RunAsync(source.Token); TestTrace.Write("Waiting for AsyncSpinWaiter to start executing"); var spinWait = spinExecuting.WaitOne(TimeSpan.FromSeconds(10)); TestTrace.Write("Cancelling workflow"); source.Cancel(); var cancelInvoked = cancellationHandlerClosed.WaitOne(Constants.Timeout); // Assert TestTrace.Assert(); Assert.IsTrue(spinWait, "The spinExecuting event was not set"); Assert.IsTrue(cancelInvoked); Assert.IsTrue( tracking.Records.Any(ActivityInstanceState.Closed, "CancellationHandler"), "The cancellation handler was not invoked"); } finally { TestTrace.Finally(); workflow.Trace(); } }
/// <summary> /// The execute. /// </summary> /// <param name="context"> /// The context. /// </param> protected override void Execute(NativeActivityContext context) { this.notify = context.GetExtension<SpinNotify>(); for (var i = 0; i < this.Loops; i++) { WorkflowTrace.Verbose( "NativeSpinWaiter loop {0} of {1}, spinning {2} iterations", i, this.Loops, this.Iterations); var token = context.GetExtension<ActivityCancellationToken>(); token.ThrowIfCancellationRequested(); if (this.isCancellationRequested) { return; } Thread.SpinWait(this.Iterations); this.notify.LoopComplete(this.Loops, this.Iterations); } WorkflowTrace.Verbose("NativeSpinWaiter done with {0} iterations", this.Iterations * this.Loops); }
/// <summary> /// Executes the spin wait /// </summary> /// <param name="token"> /// The token. /// </param> /// <param name="notify"> /// The notify. /// </param> private void DoSpinWait(ActivityCancellationToken token, SpinNotify notify) { for (var i = 0; i < this.Loops; i++) { WorkflowTrace.Verbose( "AsyncSpinWaiter loop {0} of {1}, spinning {2} iterations", i, this.Loops, this.Iterations); try { // For the token cancel if (token.IsCancellationRequested()) { WorkflowTrace.Verbose("Token requests cancel"); return; } Thread.SpinWait(this.Iterations); } finally { if (notify != null) { notify.LoopComplete(this.Loops, this.Iterations); } } } WorkflowTrace.Verbose("AsyncSpinWaiter done with {0} iterations", this.Iterations * this.Loops); }