如果我在IEnumerable(列表)中有以下顺序:
1 - 2 - 3 - 4 - 5
如果我对此运行PLINQ查询:
list.AsParallel().AsOrdered().WithDegreeOfParallelism(10).Select(
s => SomeDelegateFunction(s)).AsSequential().ToList();
对于上面的查询,我在我的日志记录(内部委托函数)中看到它使用多个线程,但不维护列表的处理顺序。 但是对于以下查询,我确实维护了序列,但使用单个线程来执行整个操作:
list.AsParallel().AsOrdered().WithDegreeOfParallelism(10).AsSequential().Select(
s => SomeDelegateFunction(s)).ToList();
两个查询之间的区别是第二个查询中的“AsSequential()”,我的问题是当我使用AsSequential()时:
1 - 为什么不使用多线程?它本可以将工作分解为:
1 - 2 (Give it to thread 1)
3 - 4 - 5 (Give it to thread 2)
相反,它确实做了1 - 2 - 3 - 4 - 5(按此顺序)但是在单个线程上做 - 为什么??
基本上我需要在ORDER中处理我的列表作为输入但是在多个线程上。
有什么想法吗?
答案 0 :(得分:4)
基本上我需要在ORDER中处理我的列表作为输入但是在多个线程上。
这些是相互排斥的要求。你可以做其中一个,但绝不能两个。
如果您不关心处理项目的顺序,您只需要确保最终结果是对象按照它们最初进入的顺序进行,因为您可以执行以下操作:
var list = new List<int> { 1, 2, 3, 4, 5 };
Parallel.For(0, list.Count, i =>
{
list[i] = Process(i);
});
如果你喜欢PLINQ超过Parallel.For
,你可以这样做:
Enumerable.Range(0, list.Count)
.AsParallel()
.WithDegreeOfParallelism(10)
.ForAll(i =>
{
list[i] = Process(i);
});
答案 1 :(得分:1)
回答你的第一个问题
为什么不使用多线程?
是AsSequential()
所做的与AsParallel()
所做的完全相反。
AsParallel()
在序数可枚举ParallelQuery<T>
上生成IEnumerable<T>
以允许在多个线程中并行执行。 AsSequential()
用于将并行执行的结果合并到一个可枚举的回调用者线程中。
回答你的第二个问题
它可能将工作分解为:
1 - 2 (Give it to thread 1)
3 - 4 - 5 (Give it to thread 2)
是的,但是如果并行执行这个序列,3可能会在1之前处理,并且它不会是顺序执行。
尽管如此,您可以明确控制PLINQ
如何将序列分解为多个分区。因此,您可以控制自己如何在多个线程之间分配数据,请参阅Custom Partitioners for PLINQ
答案 2 :(得分:0)
多线程生产者 - 消费者模式将允许您确保以相同的顺序处理项目,同时允许同时处理项目。如果你需要确保在下一个项目的处理开始之前完成每个项目的处理,那么,就像Servy所说的那样,你运气不好。
在生产者 - 消费者模式中,为了维护顺序,您可以使用线程安全队列。一个或多个生产者线程将要处理的项排入队列;在这种情况下,您将有一个生产者按顺序将列表中的项目传递给队列。然后,多个消费者线程可以将项目出列,这将按顺序排列。
有关详细信息,请参阅http://en.wikipedia.org/wiki/Producer-consumer_problem。