public void TestBackgroundCancelMultipleActions() { var exportProvider = EditorTestCompositions.EditorFeatures.ExportProviderFactory.CreateExportProvider(); var threadingContext = exportProvider.GetExportedValue <IThreadingContext>(); var listenerProvider = exportProvider.GetExportedValue <IAsynchronousOperationListenerProvider>(); // Ensure that multiple background actions are cancelled if they // use the same cancellation token. var worker = new AsynchronousSerialWorkQueue(threadingContext, listenerProvider.GetListener("Test")); var taskRunningEvent = new AutoResetEvent(false); var cancelEvent = new AutoResetEvent(false); var doneEvent = new AutoResetEvent(false); var source = new CancellationTokenSource(); var cancellationToken = source.Token; var action1Ran = false; var action2Ran = false; worker.EnqueueBackgroundWork(() => { action1Ran = true; Assert.NotSame(_foregroundSyncContext, SynchronizationContext.Current); Assert.False(cancellationToken.IsCancellationRequested); taskRunningEvent.Set(); cancelEvent.WaitOne(); cancellationToken.ThrowIfCancellationRequested(); Assert.True(false); }, "Test", source.Token); // We should not run this action. worker.EnqueueBackgroundWork(() => { action2Ran = true; Assert.False(true); }, "Test", source.Token); taskRunningEvent.WaitOne(); source.Cancel(); cancelEvent.Set(); try { worker.GetTestAccessor().WaitUntilCompletion(); Assert.True(false); } catch (AggregateException ae) { Assert.IsAssignableFrom <OperationCanceledException>(ae.InnerException); } Assert.True(action1Ran); Assert.False(action2Ran); }