what's expected in this case, is that if the user cancels the task by hitting enter, the other task hooked by ContinueWith
will run, but it's not the case, as per an AggregateException
keeps thrown despite the explicit handling in the ContinueWith
which is apparently not being executed.
any clarification on the below please?
class Program
{
static void Main(string[] args)
{
CancellationTokenSource tokensource = new CancellationTokenSource();
CancellationToken token = tokensource.Token;
Task task = Task.Run(() =>
{
while (!token.IsCancellationRequested)
{
Console.Write("*");
Thread.Sleep(1000);
}
}, token).ContinueWith((t) =>
{
t.Exception.Handle((e) => true);
Console.WriteLine("You have canceled the task");
}, TaskContinuationOptions.OnlyOnCanceled);
Console.WriteLine("Press any key to cancel");
Console.ReadLine();
tokensource.Cancel();
task.Wait();
}
}
If you pass the token as the second parameter, the task won't continue on nicely because it's really been cancelled. Instead it throws an OperationCanceledException which gets wrapped in an AggregateException. This is entirely expected. Now, if you did NOT pass the token to the task constructor then you'd see the behaviour you'd expect because because you'd only be using the token as a flag for exiting the while loop. In that case you're not really cancelling the task, you're exiting the while loop and completing the task normally.
Let's start with a few facts:
CancellationToken
as a parameter forTask.Run
it only has an effect if it's cancelled before the task started running. If the task is already running it will not be canceled.CancellationToken.ThrowIfCancellationRequested
, notCancellationToken.IsCancellationRequested
.Exception
property doesn't hold any exceptions and isnull
.AggregateException
).So this is what happens in your code:
The task starts running, because the token is not canceled. It will run until the token gets canceled. After it will end the continuation will not run because it only runs when the preceding task is canceled, and it hasn't been. When you
Wait
the task it will throw anAggregateException
with aTaskCanceledException
because the continuation was canceled (if you would remove that continuation the exception will go away).Solution:
You need to fix the task so it would actually be canceled, and remove (or null check) the exception handling because there is no exception: