我有一个集合,其中有要处理的元素,最多只能一起处理四个元素。在运行时,所有进程一起启动并且全部进入等待状态。一次仅处理四个元素。
问题是处理元素是随机选择的,因为所有线程都在等待资源释放。意味着第一个元素可以是集合中的最后一个元素。
但是,我需要按照集合中的顺序处理元素。
请告诉我如何实现这一目标?
我正在使用 TPL 和 C# 4.0
最佳答案
对于并行性,始终存在定义“按顺序”含义的问题。假设您有 100 件元素的集合。 “一次按 4 个顺序”处理它们(按照您的要求)可能意味着:
松散排序:使用 4 个线程,按照原始集合的顺序发出任务。
在这种情况下,您可以使用:
ParallelOptions po = new ParallelOptions() { MaxDegreeOfParallelism = 4 }; Parallel.ForEach(list.AsParallel().AsOrdered(), po, (item) => { // code });
如果任务不平衡,这将很快失去原始顺序,因为某些线程可能会落后于繁重的任务,但任务将按顺序分配。
严格排序:按 4 组的顺序处理它们,如下所示:
0 1 2 3 4 tasks _____________________________ barrier 4 5 6 7 4 tasks _____________________________ barrier etc.
在这种情况下,您可以使用屏障:
Barrier b = new Barrier(4); ParallelOptions po = new ParallelOptions() { MaxDegreeOfParallelism = 4 }; Parallel.ForEach(list.AsParallel().AsOrdered(), po, (item) => { // code b.SignalAndWait(); });
尽管您必须确保任务数量是 4 的倍数,否则屏障将不会在最后一次迭代时发出信号。
在单个任务中处理 4 个项目:您可以创建一个封装原始列表的 4 个项目的任务对象,然后像第一种情况一样执行简单的
Parallel.ForEach
(即每个线程将作为单个任务的一部分顺序处理 4 个项目)。这会按顺序以 4 个一组的方式发出任务,但如果任务花费太长时间,可能会再次导致某些线程落后。
关于c# - 如何并行和串行处理集合中的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12241983/