Last active
February 4, 2024 12:29
-
-
Save StephenCleary/37d95619f7803f444d3d to your computer and use it in GitHub Desktop.
How StartNew responds to CancellationToken
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
👍 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
Might be interesting to add another test that demonstrates the user delegate never executes if the token is already in the cancellation requested state before the task is created.