2010-11-13 6 views
5

¿Cómo crear una tubería de función verdadera usando C#? Tengo una idea, como las siguientes, pero no es un verdadero tubería¿Cómo implementar una verdadera función de canalización en 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; 
} 

En el código anterior cada elemento de IEnumerable<T> sería capaz de entrar en la tubería sólo después de que el elemento anterior termina de ejecutar todas las funciones (es decir, las salidas la tubería), pero de acuerdo con la definición si element1 termina de ejecutar func1 y empieza a ejecutar func2, en ese momento element2 debería comenzar a ejecutar func1 y así sucesivamente, manteniendo así el flujo continuo de datos en la tubería.

¿Es posible implementar este tipo de escenario en C#? Si es posible, por favor dame un código de ejemplo.

+0

Solo hay un único contexto de ejecución a menos que se introduzcan hilos (el enfoque alternativo con un hilo único es solo el desarrollo de resultado no perezosa en cada paso). Con los hilos, cada etapa es solo una cola FIFO que pasa mensajes alrededor de una "bomba". Los subprocesos (en realidad, concurrencia) también aumentan enormemente la complejidad, tal vez vea los métodos .NET4 "Paralelo". –

+0

No tengo problemas para introducir hilos, necesito que el trabajo se haga de todos modos ... por favor comparta algunas ideas –

+0

¿No resolvería esto PLINQ? http://msdn.microsoft.com/en-us/library/dd460688.aspx – bzlm

Respuesta

0

De comentario: Solo hay un único contexto de ejecución a menos que se introduzcan hilos (el enfoque alternativo con un hilo único es el resultado no perezoso en cada paso). Con los hilos, cada etapa es solo una cola FIFO que pasa mensajes alrededor de una "bomba". Los subprocesos (en realidad, concurrencia) también aumentan enormemente la complejidad, tal vez vea los métodos .NET4 "Paralelo".

Un método "fácil" es simplemente configurar N "inicia" utilizando Parallel.ForEach - si y solo si puede garantizar que los cálculos son libres de efectos secundarios.

Editar: Ver comentario (s).

+0

Eso fue una idea, pero en este patrón, ¿cómo me aseguro de que el resultado Enumerable esté en el mismo orden que la fuente Enumerable? –

+1

@AnindyaChatterjee: en lugar de utilizar 'Parallel.ForEach', utiliza Parallel Linq (PLINQ) mediante los métodos de extensión' ParallelEnumerable', que incluyen el ['AsOrdered'] (http://msdn.microsoft.com/en-us/library /dd642142.aspx) operador para mantener su orden de entrada. – Richard

0

Este comportamiento es más eficiente que una verdadera canalización. La canalización solo tiene sentido si las operaciones se pueden ejecutar en paralelo, pero todos estos trabajos comparten un único subproceso de CPU y, por lo tanto, deben ejecutarse de forma secuencial, incluso si se canalizan.

Si entiendes que no habrá ninguna mejora en el rendimiento y aún deseas realizar un pipeline, deja un comentario y te mostraré cómo, pero primero quiero asegurarme de que sabes lo que estás pidiendo.

+0

¿Por qué crees que la verdadera tubería no aumentará el rendimiento? De todos modos, estoy muy interesado en ver una verdadera implementación de canalización y voy a verificar el rendimiento de los dos. –

0

Creo que falta un elemento arquitectónico principal, ya sea que se trate o no el trabajo. Pipeline es muy similar a la cadena GoF tradicional de la responsabilidad, echar un vistazo aquí si usted no tiene el libro GoF en torno a:

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

Yo creo que hay que restringir su "T" para alguna de las interfaces que le dice a la tubería si el trabajo fue manejado (use la instrucción "where").

Además, eche un vistazo al marco PLINQ. Sé que no es exactamente lo que estás buscando (allí, la intención ES ejecutar varios trabajos en paralelo), pero podría darte algunas buenas ideas.

+0

Si aplico este patrón será el mismo que el código que mencioné anteriormente, de todos modos no será una verdadera tubería. –

Cuestiones relacionadas