5

考虑到延迟执行,我试图了解并行性如何使用 PLINQ 工作。这是一个简单的例子。

string[] words = { "believe", "receipt", "relief", "field" };
bool result = words.AsParallel().Any(w => w.Contains("ei"));

使用 LINQ,我希望执行达到“收据”值并返回 true,而不执行其余值的查询。

如果我们并行执行此操作,“relief”的评估可能在“receipt”的结果返回之前就开始了。但是一旦查询知道“receipt”会产生一个真实的结果,其他线程会立即让步吗?

就我而言,这很重要,因为“任何”测试可能非常昂贵,我想释放处理器以执行其他任务。

4

1 回答 1

5

不幸的是,其他线程不会立即“屈服”。

一旦Any()找到有效元素,PLINQ 调度程序将停止调度新线程以检查新元素。任何现有的分区器也将收到一个取消请求,这将阻止这些分区调用Any()另一个项目。

但是,当前您的Any()方法中执行 lambda 表达式的任何线程仍将执行,因为它们无法知道另一个线程已成功。它将阻止新线程调用Any(),但不会取消“非常昂贵”委托中的所有线程。

附带说明:

与 LINQ to Objects 不同,PLINQ 并不真正使用延迟执行。当您调用AsParallel()anIEnumerable<T>时,ParallelQuery<T>生成的 将实际开始并行处理您的例程。延迟执行将大大降低 PLINQ 的有效性,因为如果不提前创建工作分区器和调度,就不可能并行调度。


编辑:

考虑到这一点 - 如果您的 lambda 非常昂贵,您可能需要考虑使用CancellationToken。我在博客上详细介绍了 PLINQ 中的取消是如何工作的。通常,您只需使用令牌并调用ThrowIfCancellationRequested() - 但是,您也可以使用 CancellationToken 并检查IsCancellationRequested,这将使您的 lambda “提前退出”,从而为您提供一种更快停止后台处理的方法。 ..

于 2010-03-08T19:00:04.123 回答