使用OperationCanceledException自行取消任务

时间:2015-11-04 18:23:39

标签: c# async-await task cancellation

我注意到任务可以通过抛出OperationCanceledException来取消。通常,可以在OperationCanceledException constructor中传递用户友好的原因,后来成为异常消息。但是,它在任务场景中看起来并不那样。该异常使任务被取消,但最终被转换为TaskCanceledException,原始消息被替换为通用消息。

在这个例子中是否有一种简洁的方式来说明取消原因?我看了CancellationTokenSource,但没有看到任何选项。

  class Program
  {
    static async Task MyAsyncMethod()
    {
      await Task.Delay(TimeSpan.FromSeconds(1));
      throw new OperationCanceledException("My lost cancellation reason");
    }


    static void Main(string[] args)
    {
      var task = MyAsyncMethod();
      try
      {
        task.Wait();
      }
      catch (AggregateException ecxeptions)
      {
        var exception = ecxeptions.InnerException;
        Console.WriteLine(exception.GetType());       //TaskCanceledException
        Console.WriteLine(exception.Message);         //A task was canceled.
        Console.WriteLine(task.Status);               //Canceled
        Console.WriteLine(task.Exception == null);    //true
      }

      Console.Read();
    }
  }

1 个答案:

答案 0 :(得分:1)

仅当您使用Task.Wait创建一个捆绑所有内部异常的新AggregateException时,才会发生这种情况。

如果您使用await,则会抛出实际异常,并且会显示正确的消息。由于您无法在await中使用Main,因此您可以使用GetAwaiter().GetResult()同步阻止,但仍会产生与await相同的异常(没有聚合) :

static async Task MyAsyncMethod()
{
    await Task.Delay(TimeSpan.FromSeconds(1));
    throw new TaskCanceledException("My lost cancellation reason");
}

static void Main()
{
    var task = MyAsyncMethod();
    try
    {
        task.GetAwaiter().GetResult();
    }
    catch (TaskCanceledException exception)
    {
        Console.WriteLine(exception.GetType()); // TaskCanceledException
        Console.WriteLine(exception.Message); // My lost cancellation reason
        Console.WriteLine(task.Status); // Canceled
        Console.WriteLine(task.Exception == null); // true
    }

    Console.Read();
}