如何将任务中抛出的异常标记为已处理。问题是当我调用任务的Wait()
方法时,即使我很久以前已经处理过AggregateException
,它也会抛出AggregateException
。
以下代码段显示了我想要解决的问题。我的原始代码我在代码的一部分处理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();
}
上面的代码产生以下输出:
答案 0 :(得分:2)
当出现故障任务Wait
时,将重新抛出异常。如果有时会抛出异常,那将是不可靠的设计。
但是,如果你要添加一个处理异常的延续,而你又不想再抛出它,那么就不要再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
。