我目前有一个小型控制台应用程序,它运行许多任务(使用 Parallel.ForEach ),并且这些任务中的每一个都使用 ThreadPool.QueueUserWorkItem 创建子线程
我希望应用程序能够处理这些任务/线程抛出的任何异常。
如果线程抛出任何错误或者它们会不会消失, try..catch 会围绕 Parallel.ForEach 语句吗?
编辑:这些子线程模拟系统的用户。请参阅this question.
答案 0 :(得分:4)
声明周围不会做这个工作。你可以这样做:
public static void Main(string[] args)
{
string[] files = System.IO.Directory.GetFiles(@".", "*.*");
Parallel.ForEach(files, x =>
{
try
{
MyAction(x);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
});
}
static void MyAction(string x)
{
throw new ApplicationException("Testing: " + x);
}
答案 1 :(得分:2)
不要使用QUWI。我简要比较了后台任务类型on my blog(Task
,BackgroundWorker
,Delegate.BeginInvoke
,ThreadPool.QueueUserWorkItem
和Thread
)。
对于后台任务,Task
是明显的赢家。 QueueUserWorkItem
相比之下是非常低级别的。
特别是,您的问题是错误传播,Task
内置了对QueueUserWorkItem
完全缺乏的支持。通过将委托包装在try
/ catch
中,将 自己构建它,将异常存储为委托参数的一部分(或作为lambda表达式的绑定变量) ),稍后显式检查,并执行一些technically unsupported reflection以保留堆栈跟踪。
但为什么要这么麻烦? Task
支持开箱即用的错误传播。
答案 2 :(得分:1)
您可以使用try / catch处理所有异常,例如:
try
{
MyParallelMethod();
}
catch(Exception e)
{
//...
}
在你的方法中,做一些类似的事情:
public void MyParallelMethod()
{
var data = new List<String>();
//...
Parallel.ForEach(data, d =>
{
try
{
//...
}
catch (Exception e)
{
//...
}
});
}
答案 3 :(得分:0)
如果线程抛出任何错误或者它们会消失,是否会将try.catch的Parallel.ForEach语句包围起来?
不,你需要把try / catch放在子线程中。
答案 4 :(得分:0)
必须在任务本身(每个作业)中实现错误处理。您需要确保要创建的任务处理异常。
Parallel.ForEach
将不会为您处理它,因为异常将不会在调用Parallel.ForEach
的线程中引发。
替代方法是使用Task<T>
。