Bad Banana
Bad Banana

Reputation: 307

When does Task.Run(Action, CancellationToken) throw TaskCanceledException?

According to documentation Task.Run(Action, CancellationToken) throws TaskCanceledException when the task has been canceled.

When exactly does Task.Run(Action, CancellationToken) throw TaskCanceledException? It is not clear what conditions must be met for this exception to be thrown.

Upvotes: 8

Views: 5428

Answers (2)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149598

Reading Cancellation in Managed Thread:

Only the requesting object can issue the cancellation request, and each listener is responsible for noticing the request and responding to it in a timely manner.

And then goes on:

Cancellation is cooperative and is not forced on the listener. The listener determines how to gracefully terminate in response to a cancellation request.

You need to make sure you're listening on CancellationToken.IsCancelledRequested or the exception throwing CancellationToken.ThrowIfCancelltionRequested. Its your responsibility to cancel and await the operation to observethe cancellation exception.

Upvotes: 0

i3arnon
i3arnon

Reputation: 116636

There seems to be some confusion (and the documentation might be misleading).

Inoking the Task.Run method would never throw TaskCanceledException (at least with the current implementation). Unlike ArgumentNullException and ObjectDisposedException that are thrown synchronously when the "The action parameter was null" and "The CancellationTokenSource associated with cancellationToken was disposed." respectively.

Task.Run however returns a Task that may be canceled using the CancellationToken parameter (more on cancellation in here) and waiting on it with await task, task.Wait(), task.Result, etc. would throw a TaskCanceledException (possibly wrapped in an AggregateException)

Task<int> task = null;
try
{
    task = Task.Run(() => 5, new CancellationToken(true));
}
catch (TaskCanceledException)
{
    Console.WriteLine("Unreachable code");
}

try
{
    int result = await task;
}
catch (TaskCanceledException)
{
    Console.WriteLine("Awaiting a canceled task");
}

It might be clearer if the documentation had 2 sections of possible exceptions:

  1. "regular" synchronous exceptions (e.g. ArgumentNullException and ObjectDisposedException)
  2. "async" asynchronous exceptions that could only be thrown by waiting on the returned task (e.g. TaskCanceledException)

Upvotes: 8

Related Questions