2011-01-06 76 views
3

我想在C#中創建一個並行管道。我已經declaered命名的IOperation接口:C中的並行管道#

public interface IOperation<Tin, Tout> 
{ 
    BlockingCollection<Tout> BlockingCollection(IEnumerable<Tin> input); 
} 

現在我想寫一個類,它並行執行這些操作的多。 我這個蒲甘:

public class Pipeline : IPipeline 
{ 
    private List<IOperation<Object, Object>> operations = new List<IOperation<Object, Object>>(); 
    private List<BlockingCollection<Object>> buffers = new List<BlockingCollection<Object>>(); 
    public void Register(IOperation<Object, Object> operation) 
    { 
     operations.Add(operation); 
    } 

    public void Execute() 
    { 

    } 
} 

但我沒有找到任何解決方案,以節省操作和操作之間的緩衝區,因爲它們都具有不同的泛型類型。有人有想法嗎?

+1

你能說清楚「保存」是什麼意思嗎? – 2011-01-06 15:06:43

+0

我想將它們放在Pipeline類頂部的兩個列表中 – AntonS 2011-01-06 17:21:46

回答

1

您是否考慮過使用TPL中的Parallel.ForEach?
任務並行庫(TPL)是.NET 4中的一組公共類型和API。

1

您的Pipeline如何工作並不十分清楚。你爲什麼傳遞BlockingCollections?你爲什麼要使用泛型,然後把object作爲類型?

請考慮改爲使用加載類型Action類型的刪除的管道,然後使用任務並行庫創建並行執行這些操作的任務。

public void Register(Action operation) 
    { 
     operations.Add(operation); 
    } 

public void Execute() 
    { 
     foreach (var action in operations) 
      Task.StartNew(operation); 
    } 

但是,這不是一個真正的'管道',它只是一組並行執行的操作。

流水線通常會有輸入類型和輸出類型的流水線步驟。你可以通過創建類似於PipelineStep<T,U>的方法來處理這個問題,並且你將構建傳遞給Func操作的每個管道步驟。在內部,每個管道步驟可能會消耗一個輸入IEnumerable併產生一個輸出IEnumerable,它可以使用Task或更簡單地使用並行foreach循環來完成此操作。

或者,您可以使用TPL的Task.ContinueWith方法將任務從輸入鏈接到輸出。

0

關於具有BlockingCollection的並行管線,有一篇關於http://msdn.microsoft.com/en-us/library/ff963548.aspx的好文章。

基本上每個步驟都應該有一個BlockingCollection類型的輸出隊列。它接收來自上一步輸出隊列的項目,並在完成處理後將它們添加到其輸出中。

1

微軟有一些完全類似的東西 - TPL Dataflow可以讓你在管道中定義塊,並對它們如何緩衝和並行化進行精細控制。

與您的解決方案不同,它使用完全異步推送設計。它不使用BlockingCollection(阻塞拉動設計),並且如果您有深度流水線,它將顯着更快。