Skip to content

Instantly share code, notes, and snippets.

@StephenCleary
Last active February 4, 2024 12:29
Show Gist options
  • Save StephenCleary/37d95619f7803f444d3d to your computer and use it in GitHub Desktop.
Save StephenCleary/37d95619f7803f444d3d to your computer and use it in GitHub Desktop.
How StartNew responds to CancellationToken
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class StartNewCancellationTokenUnitTests
{
[TestMethod]
public void CancellationTokenPassedToStartNew_CancelsTaskWithTaskCanceledException()
{
var cts = new CancellationTokenSource();
cts.Cancel();
var task = Task.Factory.StartNew(() => { }, cts.Token);
TaskCanceledException exception = null;
try
{
task.Wait();
}
catch (AggregateException ex)
{
// TaskCanceledException derives from OperationCanceledException
exception = ex.InnerException as TaskCanceledException;
}
Assert.IsTrue(task.IsCanceled);
Assert.IsNotNull(exception);
Assert.AreEqual(cts.Token, exception.CancellationToken);
}
[TestMethod]
public void CancellationTokenObservedByDelegate_FaultsTaskWithOperationCanceledException()
{
var cts = new CancellationTokenSource();
cts.Cancel();
var task = Task.Factory.StartNew(() => { cts.Token.ThrowIfCancellationRequested(); });
OperationCanceledException exception = null;
try
{
task.Wait();
}
catch (AggregateException ex)
{
exception = ex.InnerException as OperationCanceledException;
}
Assert.IsTrue(task.IsFaulted);
Assert.IsNotNull(exception);
Assert.AreEqual(cts.Token, exception.CancellationToken);
}
[TestMethod]
public void CancellationTokenObservedAndPassed_CancelsTaskWithTaskCanceledException()
{
var cts = new CancellationTokenSource();
var taskReady = new ManualResetEvent(false);
var task = Task.Factory.StartNew(() =>
{
taskReady.Set();
while (true)
cts.Token.ThrowIfCancellationRequested();
}, cts.Token);
taskReady.WaitOne();
cts.Cancel();
OperationCanceledException exception = null;
try
{
task.Wait();
}
catch (AggregateException ex)
{
// TaskCanceledException derives from OperationCanceledException
exception = ex.InnerException as TaskCanceledException;
}
Assert.IsTrue(task.IsCanceled);
Assert.IsNotNull(exception);
Assert.AreEqual(cts.Token, exception.CancellationToken);
}
}
@StephenCleary
Copy link
Author

👍 Good point. Yes, the delegate is never actually executed if it is cancelled before it starts. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment