2015-11-04 2 views
1

J'ai remarqué que la tâche peut s'annuler en lançant OperationCanceledException. Normalement, on peut passer une raison conviviale dans le OperationCanceledExceptionconstructor qui devient plus tard le message d'exception. Cependant, cela ne ressemble pas à cela dans le scénario de tâche. L'exception rend la tâche annulée mais est finalement traduite en TaskCanceledException et le message d'origine est remplacé par un message générique.Auto annulation de la tâche avec OperationCanceledException

Existe-t-il une manière élégante d'indiquer la raison d'annulation dans cet exemple? J'ai regardé CancellationTokenSource mais n'a pas vu une option non plus.

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(); 
    } 
    } 

Répondre

1

Cela se produit uniquement lorsque vous utilisez Task.Wait ce qui crée une nouvelle AggregateException qui regroupe toutes les exceptions internes.

Si vous utilisez await, l'exception réelle est levée et le message correct s'affiche. Puisque vous ne pouvez pas utiliser await dans Main vous pouvez utiliser GetAwaiter().GetResult() qui bloque de manière synchrone mais produira toujours la même exception que await sera (sans l'agrégation):

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(); 
}