抛出异常时任务不处于故障状态

Task not in a faulted state when an exception is thrown

我似乎无法弄清楚为什么在以下示例中抛出异常时我的任务未处于故障状态(假设 engine.Send(...) 抛出异常):

       var receiverTask = new Task<Task>(async () => {
            result = await Task.FromResult(engine.Send(someObject));
        });
        receiverTask.Start();
        receiverTask.Wait();

如果我在 receiverTask.Wait() 之后执行 receiverTask.IsFaulted 它 returns false 而不是我期望的 true。

我一直在读到我需要使用类似以下结构的内容:

receiverTask.ContinueWith(t => { /* error handling */ },
    TaskContinuationOptions.OnlyOnFaulted);

但我似乎无法弄清楚如何将其集成到示例代码中。我在 Start() 之前调用它吗?在 Wait()?

之前

我希望调用程序以某种方式知道 receiverTask 抛出异常并失败。有什么指点吗?

如果我正确理解了这个上下文,您可以省略 .Start() 并以不同方式使用 .Wait()

(我不知道你的engine.Send(someObject)方法是什么,所以我不得不假设。)

假设你的方法returns是一个布尔值(没关系,只是写点东西而已。

如果是同步的,返回的Task可能是:

 Task<bool> receiverTask = Task<bool>.Run(async () =>
            await Task<bool>.FromResult(engine.Send(someObject)));

 Task<bool> receiverTask = Task.Factory.StartNew(async delegate
 {
    bool _result = await Task<bool>.FromResult(engine.Send(someObject));
    return _result;
 }, TaskScheduler.Default).Unwrap();

如果是异步的,返回的Task可能是:

 Task<bool> receiverTask = Task.Run(async () =>
            await engine.Send(someObject));

 Task<bool> receiverTask = Task.Factory.StartNew(async delegate
 {
    bool _result = await engine.Send(someObject);
    return _result;
 }, TaskScheduler.Current).Unwrap<bool>();


(但是,如果没有其他 async/await 声明,所有这些都是阻塞的)。

一旦你的任务被安排好,一些继续条件可以被定义来评估它的状态。
如果任务处于某种故障状态(取消、中止等),其 .IsCompleted 属性 报告 true,但 .Status 属性 不是 TaskStatus.RanToCompletion.

 receiverTask.ContinueWith(t =>
 {
    //Continue on faulted
    Console.WriteLine(receiverTask.GetAwaiter().IsCompleted);
    if (receiverTask.IsFaulted)
       Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
 }, TaskContinuationOptions.OnlyOnFaulted).Wait(0);

 receiverTask.ContinueWith(t =>
 {
    //Continue on canceled
    Console.WriteLine(receiverTask.GetAwaiter().IsCompleted);
    if (receiverTask.IsCanceled)
       Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
 }, TaskContinuationOptions.OnlyOnCanceled).Wait(0);

 receiverTask.ContinueWith(t =>
 {
    //Standard behaviour
    Console.WriteLine(receiverTask.GetAwaiter().IsCompleted);
    Console.WriteLine(receiverTask.Status.ToString());
 }, TaskContinuationOptions.None).Wait();

 //This writes only if no errors have been raised
 if (receiverTask.Status == TaskStatus.RanToCompletion)
    Console.WriteLine("Completed: {0}  Result: {1}", receiverTask.GetAwaiter().IsCompleted, receiverTask.Result);


但您也可以使用 Try/Catch 块:

 try
 {
    receiverTask.Wait();

    if (receiverTask.Status == TaskStatus.RanToCompletion)
       Console.WriteLine("Completed: {0}  Result: {1}", receiverTask.GetAwaiter().IsCompleted, receiverTask.Result);
 }
 catch (Exception)
 {
    receiverTask.ContinueWith(t =>
    {
       //With continuation
       if (receiverTask.IsFaulted)
          Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
    }, TaskContinuationOptions.OnlyOnFaulted);

       //or without
       //if (receiverTask.IsCanceled)
       //Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
 }