2011-05-23 62 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);