Reputation: 11
I have a simple program here
private static void CancellingSingleTask()
{
DateTime whenStarted = DateTime.Now;
Console.WriteLine("[{0}] - Main: Started", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Task task = Task.Factory.StartNew(() =>
{
int? taskId = Task.CurrentId;
Console.WriteLine("[{0}] - Task - [{1}]: Started", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
Thread.Sleep(2000);
if (ct.IsCancellationRequested)
{
Console.WriteLine("[{0}] - Task - [{1}]: Cancellation Requested", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
throw new OperationCanceledException();
}
Console.WriteLine("[{0}] - Task - [{1}]: No Cancellation Requested", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
}, ct);
Action Print = () =>
{
Console.WriteLine("[{0}] - Main: Task.IsCanceled = [{1}] Task.IsFaulted = [{2}] Task.IsCompleted = [{3}] Task.Status = [{4}]", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks),
task.IsCanceled, task.IsFaulted, task.IsCompleted, task.Status);
};
Console.WriteLine("[{0}] - Main: Started New Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
Thread.Sleep(1000);
Console.WriteLine("[{0}] - Main: Cancelling Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
cts.Cancel();
Thread.Sleep(2000);
Console.WriteLine("[{0}] - Main: After Cancelling Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
try
{
Console.WriteLine("[{0}] - Main: Waiting For Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
task.Wait();
Console.WriteLine("[{0}] - Main: After Waiting For Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
}
catch (AggregateException aggregateException)
{
Thread.Sleep(2000);
Console.WriteLine("[{0}] - Main: In Catch Block", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
foreach (var exception in aggregateException.InnerExceptions)
{
Console.WriteLine("[{0}] - Main: Received Exception In Task [{1}]", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), exception.Message);
}
}
}
Sample Output
[00:00:00.0010000] - Main: Started
[00:00:00.0040002] - Main: Started New Task
[00:00:00.0060003] - Main: IsCanceled = [False] IsFaulted = [False] IsCompleted = [False] Status = [Running]
[00:00:00.0070004] - Task - [1]: Started
[00:00:01.0070576] - Main: Cancelling Task
[00:00:02.0071148] - Task - [1]: Cancellation Requested
[00:00:03.0111722] - Main: After Cancelling Task
[00:00:03.0111722] - Main: IsCanceled = [False] IsFaulted = [True] IsCompleted = [True] Status = [Faulted]
[00:00:03.0111722] - Main: Waiting For Task
[00:00:05.0112866] - Main: In Catch Block
[00:00:05.0112866] - Main: IsCanceled = [False] IsFaulted = [True] IsCompleted = [True] Status = [Faulted]
[00:00:05.0112866] - Main: Received Exception In Task [The operation was canceled.]
I never see the Task.IsCanceled Set to true, am I making a mistake or missing something obvious. I have done a bit of research/searching on this issue but was not able to find a conclusive answer.
Note: Related Questions on StackOverFlow Cancellation of a task task IsCanceled is false, while I canceled Task.IsCancelled doesn't work
Upvotes: 1
Views: 3135
Reputation: 73502
I suppose you should pass the CancellationToken
to the constructor of OperationCanceledException
.
if (ct.IsCancellationRequested)
{
Console.WriteLine("[{0}] - Task - [{1}]: Cancellation Requested", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
throw new OperationCanceledException(ct);
}
TPL will check whether both CancellationToken
are same, if so it will mark task as Cancelled
in your case it is not and so TPL assumes your task is not cancelled.
or even better use ThrowIfCancellationRequested
method, as simple as that
ct.ThrowIfCancellationRequested();
Upvotes: 8