【发布时间】:2017-04-16 04:37:09
【问题描述】:
我有问题。 我尝试运行多个长时间运行的任务。如果一个失败,我想取消所有其他任务并获得失败异常。 下面给出的例子。 我想用
抛出的异常捕获 AggregateException throw new Exception("FailureTask");
但我捕获的是 OperationCanceledException 而不是 AggregateException,因为我想取消所有其他任务。
[TestMethod]
public void TestParallelTaskCancelation()
{
var cancellationTokenSource = new CancellationTokenSource();
Task[] tasks =
{
Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
Task.Factory.StartNew(DummyTask, cancellationTokenSource, cancellationTokenSource.Token),
Task.Factory.StartNew(FailureTask, cancellationTokenSource, cancellationTokenSource.Token)
};
try
{
Task.WaitAll(tasks, cancellationTokenSource.Token);
}
catch (OperationCanceledException e)
{
Console.WriteLine(e.GetaAllMessages());
}
catch (AggregateException e)
{
Console.WriteLine(e.GetaAllMessages());
}
}
private void DummyTask(object o)
{
var cancellationToken = (CancellationTokenSource)o;
while (true)
{
Thread.Sleep(10000);
if (cancellationToken.IsCancellationRequested)
{
cancellationToken.Token.ThrowIfCancellationRequested();
}
}
}
private void FailureTask(object o)
{
var cancellationToken = (CancellationTokenSource)o;
var executionTask = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
throw new Exception("FailureTask");
}, cancellationToken.Token);
executionTask.ContinueWith(t =>
{
cancellationToken.Cancel(false);
throw new Exception(t.Exception.GetaAllMessages());
}, TaskContinuationOptions.OnlyOnFaulted);
if (executionTask.Wait(10 * 1000, cancellationToken.Token)) return;
//timeout !!!
throw new Exception("The limit 'Max Seconds Per Query' has been exceeded!!!");
}`
请帮忙。
【问题讨论】:
-
你抛出一个
Exception,它是所有异常的基类。OperationCanceledException和AggregateException派生自Exception。您的异常永远不会被捕获,因为您只是捕获更具体的异常。要捕获AggregateException,您必须抛出AggregateException。 -
如果两个或多个任务同时失败怎么办。那么我将捕获哪个异常?据我了解,AggregateException 应该包括取消任务的取消异常和其他任务的异常。
-
抛出 throw new AggregateException("FailureTask");没用。即使只捕获(基本)异常也会捕获 OperationCanceledException。
-
@ThomasSchneiter 这不是 100% 正确的。 Taks.WaitAll 将触发“OperationCanceledException”,因为它是取消。如果您取消任务,则会抛出 AggregateException。
标签: c# exception-handling synchronization task aggregateexception