Created
March 3, 2015 01:23
-
-
Save StephenCleary/82813efb37c40a79523d to your computer and use it in GitHub Desktop.
How Task.Run 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 TaskRunCancellationTokenUnitTests | |
{ | |
[TestMethod] | |
public void CancellationTokenPassedToSynchronousTaskRun_CancelsTaskWithTaskCanceledException() | |
{ | |
var cts = new CancellationTokenSource(); | |
cts.Cancel(); | |
var task = Task.Run(() => { }, 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 CancellationTokenPassedToAsynchronousTaskRun_CancelsTaskWithTaskCanceledException() | |
{ | |
var cts = new CancellationTokenSource(); | |
cts.Cancel(); | |
var task = Task.Run(async () => { await Task.Yield(); }, 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 CancellationTokenObservedBySynchronousDelegate_FaultsTaskWithOperationCanceledException() | |
{ | |
var cts = new CancellationTokenSource(); | |
cts.Cancel(); | |
var task = Task.Run(() => { 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 CancellationTokenObservedByAsynchronousDelegate_CancelsTaskWithTaskCanceledException() | |
{ | |
var cts = new CancellationTokenSource(); | |
cts.Cancel(); | |
var task = Task.Run(async () => | |
{ | |
await Task.Yield(); | |
cts.Token.ThrowIfCancellationRequested(); | |
}); | |
OperationCanceledException exception = null; | |
try | |
{ | |
task.Wait(); | |
} | |
catch (AggregateException ex) | |
{ | |
// TaskCanceledException derives from OperationCanceledException | |
exception = ex.InnerException as TaskCanceledException; | |
} | |
Assert.IsTrue(task.IsCanceled); // Note: canceled, not faulted! | |
Assert.IsNotNull(exception); | |
Assert.AreEqual(cts.Token, exception.CancellationToken); | |
} | |
[TestMethod] | |
public void CancellationTokenObservedSynchronouslyAndPassed_CancelsTaskWithTaskCanceledException() | |
{ | |
var cts = new CancellationTokenSource(); | |
var taskReady = new ManualResetEvent(false); | |
var task = Task.Run(() => | |
{ | |
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); | |
} | |
[TestMethod] | |
public void CancellationTokenObservedAsynchronouslyAndPassed_CancelsTaskWithTaskCanceledException() | |
{ | |
var cts = new CancellationTokenSource(); | |
var taskReady = new ManualResetEvent(false); | |
var task = Task.Run(async () => | |
{ | |
await Task.Yield(); | |
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment