在向集合添加线程时处理TPL中的错误

时间:2015-01-21 18:06:51

标签: c# .net task-parallel-library async-await

我正在制作一个Producer Consumer模型,其中生成的每个项目都在新的Task Parallel Library线程上使用,并在List<Task>集合中进行跟踪。我希望能够以及时和可预测的方式捕获任何未公开的异常。在一个循环中,我从集合中删除已完成的线程,并且正在考虑类似下面的内容,但没有在网上看到任何有关此事的内容。

try
{
    Task.WaitAll(threadList.FindAll(x => x.IsFaulted).ToArray());
}
catch(AggregateException aex)
{
    //Deal with the exceptions and possibly kill the program
}

threadList.RemoveAll(x => x.IsCompleted);

由于子线程中的错误处理很好,除了像OutOfMemoryException之类的东西之外,永远不会有未处理的异常。如果发生这种情况,我想抓住它并在日志记录中优雅地消亡。

有没有更好的选择,甚至是我应该关注的设计?

2 个答案:

答案 0 :(得分:4)

我会采取略有不同的方法。 我会等待每个任务独立完成,在任务完成时递减列表:

while (threadList.Count > 0)
{
     Task finishedTask;
     try
     {
          finishedTask = await Task.WhenAny(threadList);

         // More processing if needed.
     }
     catch (Exception e)
     {
         // Handle exception.
     } 
     finally
     {
           threadList.Remove(finishedTask);     
     }
}

请注意,通过这种方式,您可以捕获特定的异常,同时让其他人无法处理。

作为旁注 - 请看TPL Dataflow。将为您处理线程模型和异常传播。

答案 1 :(得分:2)

您可能需要考虑在循环中使用Task.WaitAny(删除已完成的任务)。

这样做的好处是可以显示发生时的异常(处理“及时方式”要求),而不是等待所有任务提前完成。