使用任务并行库构建任务处理管道

时间:2013-07-25 14:49:08

标签: c# concurrency task-parallel-library system.reactive

我来自Objective-C背景,在那里我会使用Grand Central Dispatch或NSOperations来相当简单地解决这个问题。不幸的是,当我尝试在C#中构建这个问题时,我认为自己陷入了这种思维方式。

我有高级任务,每个任务都有多个可以并行发生的部分。这些部分中的每一部分都需要经历管道中的几个阶段。我需要构造这个管道,但知道高级任务何时完成,并执行回调。

使用GCD,我会创建队列来执行部件,每个部件链接到流程的下一部分。所有这些部分都将根据它们所属的高级任务进行分组,以便最终可以触发回调。

我正在努力弄清楚这在C#中是如何工作的。我大部分时间都在研究任务并行库,但对我使用的内容没有特别的偏好。到目前为止我遇到的一个问题是,如果你完成处理,那么完成回调似乎只能用TPL管道完成,但是因为我将有多个任务不会发生。

从概览的角度来看,这个问题最好如何构建?我想知道用Rx编写提供并发性的系统是否更好?

3 个答案:

答案 0 :(得分:1)

我不太明白你的意思是完成回调因为有多个任务而无法选择。为每个任务构建数据流网络意味着为他们单独触发完成。

我猜你想避免每次重建网络所产生的开销?在这种情况下,也许你可以在最后添加一个直通块:它返回它给出的任何输入,并且还调用你需要的任何回调。因此,对于网络生成的每个输出,都将调用回调。如果你想更进一步,它可以将消息发送到另一个块,然后可以并行调用回调。

或者,如果管道足够简单,并且您不需要额外的缓冲等等,也许您可​​以使用普通的TPL任务来完成它?像这样:

public async Task<string> HighLevelTask(string input1, string input2, Action completed) {
    Task<string[]> parts = Task.WhenAll(Part1(input1), Part2(input2));
    string[] results = await parts;
    completed();
    return string.Join(",", results);
}
public async Task<string> Part1(string input) {
    var result1 = await Stage1(input);
    var result2 = await Stage2(result1);
    return result2;
}

答案 1 :(得分:0)

听起来像TPL Dataflow是正确的方法。 Rx可以执行Dataflow可以执行的任何操作,但在事件/时间管理方面确实优秀,而Dataflow的语法对于实际数据流(包括管道)更清晰。

您是正确的,Dataflow没有内置任何类型的每项完成通知。您必须自己添加,例如,在每个项目的末尾加上ActionBlock

您可能会发现我的AsyncEx library很有用。特别是,我有一些asynchronous coordination primitives,包括AsyncCountdownEvent,听起来可能就是你所需要的。

答案 2 :(得分:0)

TPL足以解决您的问题。我建议您阅读MSDN about pipelines in TPL上的这篇文章。