5

如何使用 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# 中实现吗?如果可能,请给我一些示例代码。

4

3 回答 3

0

这种行为比真正的管道更有效。只有当操作可以并行运行时,流水线才有意义,但所有这些作业都共享一个 CPU 线程,因此即使是流水线也必须按顺序执行。

如果您知道不会有任何性能改进并且仍然想要管道,请发表评论,我会展示如何,但我首先要确保您知道您的要求。

于 2010-11-13T17:31:26.820 回答
0

我相信一个主要的架构元素丢失了,不管工作是否被处理。Pipeline 与传统的 GoF 责任链非常相似,如果您身边没有 GoF 书籍,请看这里:

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

我认为你必须将你的“T”限制在某个接口,告诉管道是否处理了工作(使用“where”语句)。

另外,看看 PLINQ 框架。我知道这并不完全是您正在寻找的(在那里,目的是并行执行多个作业),但它可能会给您一些好主意。

于 2010-11-13T17:37:55.963 回答
0

来自评论:除非引入线程,否则只有一个执行上下文(单线程的替代方法只是在每个步骤中构建非延迟结果)。对于线程,每个阶段只是一个 FIFO 队列,通过“泵”传递消息。线程(实际上是并发)也大大增加了复杂性,也许可以看到 .NET4“并行”方法。

“简单”的方法就是使用Parallel.ForEach配置 N 个“开始” ——当且仅当您可以保证计算没有副作用。

编辑:见评论。

于 2010-11-13T17:38:30.657 回答