2011-03-16 23 views
2

我现在有一个运行多个任务的小型控制台应用程序(使用Parallel.ForEach)和这些任务的每一个创建使用线程池子线程.QueueUserWorkItem如何捕捉控制台应用程序从工作线程错误使用C#编写

我想应用程序来处理这些任务/线程抛出的任何异常。

将围绕Parallel.ForEach语句在try..catch工作,如果线程抛出任何错误或他们只会死了呢?

编辑:这些子线程模拟系统的用户。请参阅this question.

+0

嗨,应该有一些事件处理程序添加Thread.UnhandledException或类似... – 2011-03-16 12:40:36

+3

为什么你要在'Parallel.ForEach'循环中的任务内调用'ThreadPool.QueueUserWorkItem'? – 2011-03-16 12:41:03

+0

如果你围绕Parallel.ForEach它应该抓住的任何循环迭代中引发的任何异常。它会更好把try/catch语句内的for循环您捕捉实际的异常的源泉,而不是当它抛出的并行算法的呀?也可能取决于你试图捕捉什么异常 – timothyclifford 2011-03-16 12:46:38

回答

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); 
} 
0

会与周围的工作在try..catch的Parallel.ForEach声明如果线程抛出任何错误或他们只会死了呢?

不,你需要把try/catch放在子线程内。

0

错误处理必须在任务本身(每个作业)来实现。您需要确保您正在创建的任务处理异常。

Parallel.ForEach将不会为您处理它,因为在调用Parallel.ForEach的线程中不会引发异常。

选择是使用Task<T>

1

你可以处理的try/catch所有的异常,例如:

try 
{ 
    MyParallelMethod(); 
} 
catch(Exception e) 
{ 
    //... 
} 

,并在你的方法,做这样的事情:

public void MyParallelMethod() 
{ 
    var data = new List<String>(); 
    //... 

    Parallel.ForEach(data, d => 
    { 
     try 
     { 
      //... 
     } 

     catch (Exception e) 
     { 
      //...  
     } 
    }); 
} 
2

请勿使用QUWI。我有后台任务类型简要对比on my blogTaskBackgroundWorkerDelegate.BeginInvokeThreadPool.QueueUserWorkItemThread)。

后台任务,Task是明显的赢家。与之相比,QueueUserWorkItem非常低级。

特别是,你的问题是错误传播,Task内置支持这完全缺乏QueueUserWorkItem。您可以通过包装在try/catch您的代理,存储例外作为委托参数的一部分构建它自己(或lambda表达式的约束变量),明确检查它后,并做一些technically unsupported reflection保存堆栈跟踪。

但为什么要麻烦? Task支持开箱即用的错误传播。

相关问题