异常延续不适用于完成继续

时间:2012-10-24 11:41:56

标签: .net exception-handling task-parallel-library continuations

我有这个简单的TPL代码:

var t = Task.Factory.StartNew(() => { throw null; })
    .ContinueWith((ant) => { Console.WriteLine("Success"); }, 
        TaskContinuationOptions.OnlyOnRanToCompletion)
    .ContinueWith((ant) => { Console.WriteLine("Error"); }, 
        TaskContinuationOptions.OnlyOnFaulted);
t.Wait();

我得到一个未处理的例外:

Unhandled Exception: System.AggregateException: One or more errors occurred.
...

如果我将t.Wait()放在try-catch中,那么异常会被捕获,我知道它违反了使用异常延续的全部要点。现在,如果我删除完成继续,任务抛出的异常将在异常延续中处理,我不会得到上述异常。有人可以对发生的事情有所了解吗? 我使用的是VS2010 SP1和.NET 4.0

1 个答案:

答案 0 :(得分:3)

ContinueWith()未返回原始Task,它返回表示延续的Task。在您的情况下,取消继续,因为原始Task没有运行完成。由于第二个Task没有出现故障,您的第三个Task也被取消了,这就是为什么TaskCanceledExceptionAggregateException包裹起来的原因。

你可以做的是有一个延续,这两个动作都可以。类似的东西:

var t = Task.Factory.StartNew(() => { throw null; })
    .ContinueWith(
        ant =>
        {
            if (ant.IsFaulted)
                Console.WriteLine("Error");
            else
                Console.WriteLine("Success");
        });

如果您经常这样做,可以为此创建一个扩展方法(加上可能是Task<T>的通用版本,Action<T>onSuccess):

public static Task ContinueWith(
    this Task task, Action onSuccess, Action<AggregateException> onError)
{
    return task.ContinueWith(
        ant =>
        {
            if (ant.IsFaulted)
                onError(task.Exception);
            else
                onSuccess();
        });
}

用法:

var t = Task.Factory.StartNew(() => { throw null; })
    .ContinueWith(
        () => { Console.WriteLine("Success"); },
        ex => { Console.WriteLine("Error"); });
t.Wait();

此外,假设您知道您的原始Task不会被取消。如果情况并非如此,那么还需要处理一个案例。