我有这个简单的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
答案 0 :(得分: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>
的通用版本,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
不会被取消。如果情况并非如此,那么还需要处理一个案例。