如何使用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 :(得分:0)
此行为比真正的管道更有效。如果操作可以并行运行,则管道传输才有意义,但所有这些作业共享一个CPU线程,因此即使是流水线也必须按顺序执行。
如果您了解不会有任何性能改进并且仍想进行管道,请发表评论,我会说明如何,但我首先要确保您知道您要求的内容。
答案 1 :(得分:0)
我相信缺少一个主要的建筑元素,无论工作是否得到处理。 Pipeline与传统的GoF责任链非常相似,如果您没有GoF书籍,请查看此处:
http://www.dofactory.com/Patterns/PatternChain.aspx#_self1
我认为您必须将“T”限制为某个界面,该界面告诉管道是否处理了作业(使用“where”语句)。
另外,请看一下PLINQ框架。我知道这不是你想要的(在那里,意图是并行执行几个工作),但它可能会给你一些好主意。
答案 2 :(得分:0)
来自评论:除非引入了线程,否则只有一个执行上下文(使用单线程的替代方法只是每个步骤中构建的非惰性结果)。对于线程,每个阶段只是一个FIFO队列,在“泵”周围传递消息。线程(实际上,并发)也大大增加了复杂性,也许可以看到.NET4“并行”方法。
“简单”方法只是使用Parallel.ForEach配置N“开始” - 当且仅当您可以保证计算是无副作用的时候。
修改:查看评论。