2011-05-23 66 views
2

我有一组沿着这些线路设置很好的结构化对象的:线程列表4

abstract class Data 
{ 
    public abstract void GetData(); 
    public abstract void Process(); 
} 
abstract class DataSource1 : Data 
{ 
    public void GetData() { ... } 
} 
class DataSource1ProcessorA : DataSource1 
{ 
    public void Process() { ... } 
} 
abstract class DataSource2 : Data 
{ 
    public void GetData() { ... } 
} 
class DataSource2ProcessorA : DataSource2 
{ 
    public void Process() { ... } 
} 
class DataSource2ProcessorB : DataSource2 
{ 
    public void Process() { ... } 
} 

目前,我在处理每个DataSourceProcessor顺序,它开始变得只要我们添加更多来源和处理器。每个源都完全不相关,但每个处理器都需要按顺序运行。所以我需要一种方法将

new List<List<Data>> tasks = new List<List<Data>>() 
{ 
    new List<Data>() { new DataSource1ProcessorA() }, 
    new List<Data>() { new DataSource2ProcessorA(), new DataSource2ProcessorB() } 
} 
foreach (List<Data> source in tasks) 
{ 
    foreach(Data data in source) 
    { 
    data.GetData(); 
    data.Process(); 
    } 
} 

分成一系列的任务。我之前和Tasks一起工作过,虽然我没有对它们做过任何复杂的工作,但我无法弄清楚如何用任意顺序的调用顺序来触发任意数量的任务。

我不需要以任何方式访问任务,除了踢出它们并报告它们抛出的任何错误。 DataSource2ProcessorA中的一个错误最好不能阻止DataSource2ProcessorB运行,但如果编码更容易让一个错误杀死整个DataSource的线程,我可以忍受这一点。下面

回答

1

您想要使用并行foreach以及为每个项目处理列表的操作。那就是:

new List<List<Data>> tasks = new List<List<Data>>() 
{ 
    new List<Data>() { new DataSource1ProcessorA() }, 
    new List<Data>() { new DataSource2ProcessorA(), new DataSource2ProcessorB() } 
} 

Parallel.ForEach(tasks, (items) => 
{ 
    foreach (var item in items) 
    { 
     item.GetData(); 
     item.Process(); 
    } 
}); 

也就是说,虽然这保证了DataSource2ProcessorA处理DataSource2ProcessorB之前,没有关于其任务的运行顺序的保证。

+0

我知道可能有某种方式可以使用Parallel来完成此操作,但我正在考虑嵌套的Parallels和ContinueWith操作。我从来没有考虑过只使用里面的“老派”foreach循环。 (我也不确定如何通过列表。)谢谢! – Bobson 2011-05-23 19:35:19

2

用火关每个处理事件上的一个单独的线程并记录错误(或重新抛出异常):

Task.Factory.StartNew(() => { data.GetData(); data.Process(); }) 
.ContinueWith(t => Logger.Error("An exception occurred while processing. Check the inner exception for details", t.Exception), 
TaskContinuationOptions.OnlyOnFaulted);