0

我有这个简单的 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()输入 a try-catch,异常就会被捕获,我知道它违背了使用异常延续的全部意义。现在,如果我删除完成延续,任务引发的异常将在异常延续中处理,我没有得到上述异常。有人可以对正在发生的事情有所了解吗?我正在使用 .NET 4.0 的 VS2010 SP1

4

1 回答 1

3

ContinueWith()不返回原来的Task,它返回一个Task代表延续。在您的情况下,继续被取消,因为原始Task文件没有完成。而且因为第二个Task没有出错,你的第三个Task也被取消了,这就是你被TaskCanceledException包裹在里面的原因AggregateException

相反,您可以做的是有一个延续,它同时执行这两项操作。就像是:

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

如果你经常做这样的事情,你可以为此创建一个扩展方法(加上可能是Task<T>with Action<T>as的通用版本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不会被取消。如果不是这种情况,那就是您需要处理的另一种情况。

于 2012-10-24T17:48:21.897 回答