将任务异常标记为已处理

时间:2014-11-27 21:24:37

标签: c# .net exception-handling task-parallel-library aggregateexception

如何将任务中抛出的异常标记为已处理。问题是当我调用任务的Wait()方法时,即使我很久以前已经处理过AggregateException,它也会抛出AggregateException。 以下代码段显示了我想要解决的问题。我的原始代码我在代码的一部分处理AggregateException,并在代码的另一部分调用Wait()方法。但问题是一样的。

static void Main(string[] args)
{
    Task task = null;

    try
    {
        task = new Task(() =>
        {
            Console.WriteLine("Task started");
            Thread.Sleep(1000);
            throw new InvalidOperationException("my test exception");
        });

        task.ContinueWith(t => 
        {
            Console.WriteLine("Task faulted");
            AggregateException ae = t.Exception;
            ae.Flatten().Handle(ex =>
            {
                if (typeof(InvalidOperationException) == ex.GetType())
                {
                    Console.WriteLine("InvalidOperationException handled --> " + ex.Message);
                    return true;
                }

                return false;
            });
        }, TaskContinuationOptions.OnlyOnFaulted);

        task.Start();
        Thread.Sleep(2000);
        task.Wait();
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("AggregateException thrown again!!! Why???");
        ae.Flatten().Handle(ex =>
            {
                Console.WriteLine(ex.Message);
                return true;
            });              
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    Console.WriteLine("Finished");
    Console.Read();
}

上面的代码产生以下输出:

  • 任务已开始
  • 任务出错
  • 处理了InvalidOperationException - >我的测试例外
  • 再次抛出AggregateException !!!为什么???
  • 我的测试例外
  • 完成

1 个答案:

答案 0 :(得分:2)

当出现故障任务Wait时,将重新抛出异常。如果有时会抛出异常,那将是不可靠的设计。

但是,如果你要添加一个处理异常的延续,而你又不想再抛出它,那么就不要再Wait那个任务了。 Wait继承任务(您当前未使用)。它只会在原始任务完成后完成,如果你需要结果,只需要继续返回。这样,异常只会被处理一次:

Task continuation = task.ContinueWith(t => 
{
    Console.WriteLine("Task faulted");
    AggregateException ae = t.Exception;
    ae.Flatten().Handle(ex =>
    {
        if (typeof(InvalidOperationException) == ex.GetType())
        {
            Console.WriteLine("InvalidOperationException handled --> " + ex.Message);
            return true;
        }

        return false;
    });
}, TaskContinuationOptions.OnlyOnFaulted);

task.Start();
Thread.Sleep(2000);
continuation.Wait();

注意:当原始任务没有抛出异常时会抛出TaskCanceledException,因为取消了延续(由于TaskContinuationOptions.OnlyOnFaulted)。为避免这种情况,只需删除标记并检查t.IsFaulted