【问题标题】:Waiting on a Task with a OnlyOnFaulted Continuation causes an AggregateException等待具有 OnlyOnFaulted Continuation 的任务会导致 AggregateException
【发布时间】:2011-07-04 15:59:29
【问题描述】:

我有一些简单的代码作为重现:

var taskTest = Task.Factory.StartNew(() =>
{
    System.Threading.Thread.Sleep(5000);

}).ContinueWith((Task t) =>
{
    Console.WriteLine("ERR");
}, TaskContinuationOptions.OnlyOnFaulted);

try
{
    Task.WaitAll(taskTest);
}
catch (AggregateException ex)
{
    foreach (var e in ex.InnerExceptions)
        Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
}

但是,我在 try catch 块中抛出了一个意外的 TaskCanceledException(它位于 AggregateException InnerExceptions 对象中)。 “任务已取消”。

为什么我会收到此异常?任务的继续永远不会触发,它没有产生异常,但我在等待时仍然得到聚合异常......

我希望有人能解释这对我有什么意义:)

【问题讨论】:

  • 我的情况和你一模一样。我认为只传播上一个任务的结果会更加优雅和直观。抛出一个 TaskCanceledException 是相当令人惊讶的......

标签: c# parallel-processing task task-parallel-library pfx


【解决方案1】:

您不是在等待 OnlyOnFaulted 延续的任务 - 您正在等待on 该延续(由ContinueWith 返回)。延续永远不会触发,因为原始任务正常返回,所以它的行为就像它被取消一样。

对我来说很有意义。

我怀疑你想创建任务,添加延续,然后等待 原始 任务:

var taskTest = Task.Factory.StartNew(() =>
{
    System.Threading.Thread.Sleep(5000);

});
taskTest.ContinueWith((Task t) =>
{
    Console.WriteLine("ERR");
}, TaskContinuationOptions.OnlyOnFaulted);

【讨论】:

  • 很好的解释,只有一条评论,在这种情况下,最好不要使用 Factory.StartNew() 方法,因为任务可以在定义延续之前开始。在这里,我将使用 new Task() ctor,然后设置 ContinueWith(),最后调用 Start() 方法。有意义吗?
  • @JorgeFioranelli:为什么在定义延续之前启动任务会有问题?我相信 TPL 会毫无问题地处理这个问题。
  • 不确定,但我相信有可能任务在添加延续之前抛出异常,然后不会调用处理程序。我说的对吗?
  • @JorgeFioranelli - 如果延续附加到已完成的任务,如果任务完成但出现异常,它将立即执行。 (如果任务没有出错,它将取消。)
  • 如果我们等待原始任务,并且我们比它的异常处理继续完成更快,那么应用程序可以在异常处理程序完成之前退出,对吗?我们怎样才能最好地避免这种情况?等待继续,但不考虑它是如何完成的? await continuationTask.ContinueWith(task => {});
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 2023-04-04
  • 1970-01-01
  • 2018-09-11
  • 2013-06-16
相关资源
最近更新 更多