Task.WaitAll, how to find the tasks causing AggregateException

非 Y 不嫁゛ 提交于 2020-05-11 06:40:44

问题


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?


回答1:


You still have the list of Tasks, and each Task has an Exception property. Using that you can figure out which exceptions belong with which Task.

But, if you can, it'd be better to use Task.WhenAll or TaskFactory.ContinueWhenAll than do a blocking Wait.




回答2:


var throwers = tasks.Where(task => task.Exception != null);



回答3:


        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.");
                    }
                }
            });



回答4:


Option1 (credit to @theodor-zoulias comment):

You can set the Exception.Data property with the task name:

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:

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:

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

Exception was thrown by t2



来源:https://stackoverflow.com/questions/18314046/task-waitall-how-to-find-the-tasks-causing-aggregateexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!