【问题标题】:Mark task exception as handled将任务异常标记为已处理
【发布时间】:2015-01-26 12:46:04
【问题描述】:

如何将任务中引发的异常标记为已处理。问题是当我调用任务的Wait() 方法时,即使我很久以前已经处理了AggregateException,它也会抛出AggregateException。 以下代码 sn -p 显示了我要解决的问题。在我的原始代码中,我在代码的一部分中处理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 再次抛出!!!为什么???
  • 我的测试异常
  • 完成

【问题讨论】:

  • 似乎没有办法将异常标记为已处理。如果任务状态出错,调用 wait 方法总是会抛出 AggregateException。

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


【解决方案1】:

当错误任务被Waited 时,异常被重新抛出。如果只是偶尔抛出异常,那将是不可靠的设计。

但是,如果您要添加一个处理异常的延续,并且您不希望它再次抛出,那么就不要再次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

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 2015-11-03
    • 2015-07-15
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    相关资源
    最近更新 更多