[英]Task.WaitAll, how to find the tasks causing AggregateException
Let's say that I got the following code:假设我得到了以下代码:
var tasks = BuildTaskList();
try
{
Task.WaitAll(tasks.ToArray());
}
catch (AggregateException exception)
{
}
How do I know which task threw which of the exceptions in exception.InnerExceptions
?我怎么知道哪个任务在 exception.InnerExceptions 中抛出了哪些
exception.InnerExceptions
?
You still have the list of Tasks
, and each Task
has an Exception
property.您仍然拥有
Tasks
列表,并且每个Task
都有一个Exception
属性。 Using that you can figure out which exceptions belong with which Task
.使用它,您可以确定哪些异常属于哪个
Task
。
But, if you can, it'd be better to use Task.WhenAll
or TaskFactory.ContinueWhenAll
than do a blocking Wait.但是,如果可以,最好使用
Task.WhenAll
或TaskFactory.ContinueWhenAll
不是阻塞等待。
var throwers = tasks.Where(task => task.Exception != null);
var t1 = Task.Factory.StartNew(() => Console.WriteLine("Task 1"));
var t2 = Task.Factory.StartNew(() => Console.WriteLine("Task 2"));
var t3 = Task.Factory.StartNew(() => { throw new InvalidOperationException(); });
var t4 = Task.Factory.StartNew(() => Console.WriteLine("Task 4"));
Task.Factory.ContinueWhenAll(new[] { t1, t2, t3, t4 }, tasks =>
{
foreach (var t in tasks)
{
if (t.Status == TaskStatus.Faulted)
{
// this will run for t3
Console.WriteLine("This task has been faulted.");
}
}
});
Option1 (credit to @theodor-zoulias comment):选项1(归功于@theodor-zoulias 评论):
You can set the Exception.Data
property with the task name:您可以使用任务名称设置
Exception.Data
属性:
var task1 = Task.Factory.StartNew(() =>
{
try
{
throw new Exception();
}
catch (Exception exception)
{
exception.Data["task"] = "task1";
throw exception;
}
});
var task2 = Task.Factory.StartNew(() =>
{
try
{
throw new Exception();
}
catch (Exception exception)
{
exception.Data["task"] = "task2";
throw exception;
}
});
try
{
Task.WaitAll(task1, task2);
}
catch (AggregateException ae)
{
foreach (var exception in ae.InnerExceptions)
{
Console.WriteLine($"Exception was thrown by {exception.Data["task"]}");
}
}
Option2:选项2:
If you don't mind loosing the name of the exception's assembly information, You can set the Exception.Source
( doc ) property of the thrown exception based on the task name and look at it while iterating:如果您不介意丢失异常程序集信息的名称,您可以根据任务名称设置抛出异常的
Exception.Source
( doc ) 属性并在迭代时查看它:
var t1 = Task.Factory.StartNew(() =>
{
throw new Exception() { Source = "t1" };
});
var t2 = Task.Factory.StartNew(() =>
{
throw new Exception() { Source = "t2" };
});
try
{
Task.WaitAll(t1, t2);
}
catch (AggregateException ae)
{
foreach (var exception in ae.InnerExceptions)
{
Console.WriteLine($"Exception was thrown by {exception.Source}");
}
}
Will output:将输出:
Exception was thrown by t1
异常被 t1 抛出
Exception was thrown by t2
异常被 t2 抛出
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.