2010-11-13 4 views
5

Как создать истинный конвейер функции с использованием C#? Я получил некоторое представление о том, как как следует, но это не истинный трубопроводКак реализовать истинный конвейер функции в C#?

public static IEnumerable<T> ForEachPipeline<T>(this IEnumerable<T> source, params Func<T, T>[] pipeline) 
{ 
foreach (var element in source) { 
    yield return ExecutePipeline(element, pipeline); 
} 
} 

private static T ExecutePipeline<T>(T element, IEnumerable<Func<T, T>> jobs) 
{ 
var arg = element; 
T result = default(T); 
foreach (var job in jobs) { 
    result = job.Invoke(arg); 
    arg = result; 
} 
return result; 
} 

В приведенном выше коде каждый элемент IEnumerable<T> бы смог попасть в трубопровод только после того, как предыдущий элемент заканчивается выполнение всех функций (то есть выходы конвейер), но в соответствии с определением, если element1 завершает выполнение func1 и начинает выполнение func2, к этому времени element2 должен начать выполнение func1 и т. д., тем самым сохраняя продолжающийся поток данных в конвейере.

Можно ли реализовать такой сценарий на C#? Если возможно, пожалуйста, дайте мне примерный код.

+0

Существует только один контекст выполнения, если не введены потоки (альтернативный подход с одним потоком - это просто нелогичное построение результата на каждом шаге). С потоками каждый этап представляет собой только очередь FIFO, передающую сообщения вокруг «насоса». Темы (фактически, параллелизм) также значительно увеличивают сложность, возможно, см. Методы .NET4 «Parallel». – 2010-11-13 17:28:04

+0

У меня нет проблем с введением потоков, мне нужно, чтобы все было сделано. Пожалуйста, поделитесь некоторыми идеями. –

+0

Разве PLINQ не решит это? http://msdn.microsoft.com/en-us/library/dd460688.aspx – bzlm

ответ

0

От комментария: Существует только один контекст выполнения, если не введены нити (альтернативный подход с одним потоком - это просто нелогичное построение результата на каждом шаге). С потоками каждый этап представляет собой только очередь FIFO, передающую сообщения вокруг «насоса». Темы (фактически, параллелизм) также значительно увеличивают сложность, возможно, см. Методы .NET4 «Parallel».

Метод «простой» - это просто настроить «старты» с помощью Parallel.ForEach - тогда и только тогда, когда вы можете гарантировать, что вычисления свободны от побочных эффектов.

Редактировать: Показать комментарий (а).

+0

Это была идея, но в этом шаблоне, как я могу гарантировать, что результат Enumerable находится в том же порядке, что и источник Enumerable? –

+1

@AnindyaChatterjee: Вместо использования 'Parallel.ForEach' используйте Parallel Linq (PLINQ) с помощью методов расширения ParallelEnumerable, которые включают в себя [' AsOrdered'] (http://msdn.microsoft.com/en-us/library /dd642142.aspx) для поддержания порядка ввода. – Richard

0

Это поведение более эффективно, чем истинный трубопровод. Конвейерная обработка имеет смысл только в том случае, если операции могут выполняться параллельно, но все эти задания разделяют один поток ЦП и поэтому должны выполняться последовательно, даже если они конвейерны.

Если вы понимаете, что улучшения производительности не будет и все еще хотите конвейер, оставьте комментарий, и я покажу, как, но сначала я хочу убедиться, что вы знаете, о чем вы просите.

+0

Почему вы думаете, что истинный трубопровод не увеличит пропускную способность? В любом случае, я очень заинтересован, чтобы увидеть истинную реализацию трубопровода, и я проверю пропускную способность этих двух. –

0

Я считаю, что отсутствует один главный архитектурный элемент, независимо от того, обрабатывается ли задание или нет. Трубопровод очень похож на традиционной GoF цепи ответственности, посмотрите здесь, если у вас нет книги GoF вокруг:

http://www.dofactory.com/Patterns/PatternChain.aspx#_self1

Я думаю, что вы должны ограничить «T» в какой-то интерфейс, сообщает конвейер, если работа была обработана (используйте оператор «где»).

Кроме того, взгляните на структуру PLINQ. Я знаю, что это не совсем то, что вы ищете (там, намерение IS выполнять несколько работ параллельно), но это может дать вам несколько хороших идей.

+0

Если я применил этот шаблон, он будет таким же, как и код, упомянутый выше, в любом случае он не будет истинным конвейером. –