noseratio
noseratio

Reputation: 61666

Options for cancelling a task and waiting for its termination

I need to cancel a pending task and await for its termination before the code flow can continue. Usually, I do this:

if (this.task != null)
{
    this.taskCancellationTokenSource.Cancel();
    try
    {
        await this.task;
        // I don't need to know the result, just log it
        Debug.Print(this.task.Status.ToString());
    }
    catch (Exception e)
    {
        // I don't need to know the result, just log it
        Debug.Print(e.ToString());
    }
}

I just realized I can do the same without try/catch:

if (this.task != null)
{
    this.taskCancellationTokenSource.Cancel();
    await this.task.ContinueWith(
        // I don't need to know the result, just log it
        (t) => Debug.Print(((object)t.Exception ?? (object)t.Status).ToString()), 
        TaskContinuationOptions.ExecuteSynchronously)
}

Am I missing any reason for which I should stick to the first approach?

Upvotes: 1

Views: 133

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456507

Am I missing any reason for which I should stick to the first approach?

Two reasons, off the top of my head:

  1. ContinueWith will use the current scheduler by default, which may cause concurrency issues or surprising behavior.
  2. The antecedent task (t in your example) will have any exceptions wrapped in an AggregateException when you read the Task.Exception property.

I recommend using await instead of ContinueWith because it has more reasonable behavior in both of these cases. await will capture the current context and use that to schedule the continuation, and await will not wrap exceptions in AggregateException.

If you do use ContinueWith, then you should always explicitly specify a TaskScheduler for the continuation to run on.

Upvotes: 2

Related Questions