0

如果我在 IEnumerable (list) 中有以下顺序:

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 中处理我的列表。

有任何想法吗 ?

4

3 回答 3

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);
    });
于 2012-11-30T19:29:19.850 回答
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将序列分解为多个分区。因此,您可以控制自己的数据如何在多个线程之间分布,请参阅PLINQ 的自定义分区器

于 2012-11-30T20:42:09.150 回答
0

多线程生产者-消费者模式将允许您确保以相同的顺序处理项目,同时允许同时处理项目。但是,如果您需要确保每个项目的处理在下一个项目的处理开始之前完成,那么您就不走运了,正如 Servy 所说。

在生产者-消费者模式中,为了维护顺序,您可以使用线程安全队列。一个或多个生产者线程将要处理的项目排入队列;在这种情况下,您将有一个生产者将列表中的项目按顺序传递到队列。然后,多个消费者线程可以使项目出列,这将是有序的。

有关详细信息,请参阅http://en.wikipedia.org/wiki/Producer-consumer_problem

于 2012-11-30T19:46:59.800 回答