Under what circumstances is a deferred task expected to throw TaskCanceledException?
I am taking advantage of the asynchronous pattern execution capability while handling cancellation of asynchronous operations:
public async Task InvokeAsync(CancellationToken cancellationToken)
{
using(cancellationToken.Register(handler.Stop))
{
try
{
await handler.HandleAsync();
}
catch(HandlerStoppedException ex)
{
cancellationToken.ThrowIfCancellationRequested();
throw;
}
}
}
The method calls an asynchronous component that provides some kind of cancellation mechanism. The cancellation token sets up a callback to invoke the cancellation mechanism when the token signals cancellation request is requested.
I can call this method in my tests to implement its function during the timeout.
async Task TestInvoke()
{
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10))
{
try
{
await InvokeAsync(timeout.Token);
}
catch (TaskCancelledException ex)
{
if (ex.CancellationToken == timeout.Token)
{
throw new TimeoutException(
"Operation failed to complete in the allowed time.", ex);
}
throw;
}
}
}
My expectation is that throwing OperationCanceledException
inside a method async
will cause the method returned by the Task
method to return to the Canceled state. Then I expect any attempts to wait for this canceled task to return TaskCanceledException
.
In my current scenario (the code is very similar to the one above) I get instead OperationCanceledException
when I wait for this task. If I look at the status of the task, I see that it is in the Canceled state and has no exception associated with it.
More curious, if I call Wait()
in the task, it will select the AggregateException
one containing the expected instead TaskCanceledException
.
Under what circumstances will an expected canceled task kick out OperationCanceledException
instead of the more typical one TaskCanceledException
?
source to share
Under what circumstances will an awaited canceled task kick out
OperationCanceledException
instead of a more typical oneTaskCanceledException
?
This question is too broad. Even if we list all the scenarios where this happens today, this may change tomorrow.
I'll say this instead:
-
TaskCanceledException
is not more typical. It was originally used in task-based dynamic parallelism, which has nothing to do with asynchronous programming. -
OperationCanceledException
is the base class forTaskCanceledException
. In your code, you should never breakTaskCanceledException
(unless you are doing parallelism dynamic tasks and to accessTaskCanceledException.Task
).
Just catch it OperationCanceledException
.
source to share