我正在尝试了解在延迟执行的情况下并行性如何使用 PLINQ 工作。这是一个简单的例子。
string[] words = { "believe", "receipt", "relief", "field" };
bool result = words.AsParallel().Any(w => w.Contains("ei"));
使用 LINQ,我希望执行达到“receipt”值并返回 true,而不执行对其余值的查询。
如果我们并行执行此操作,则“relief”的评估可能在“receipt”的结果返回之前就已开始。但是一旦查询知道“receipt”会导致一个 true 的结果,其他线程会立即 yield 吗?
在我的例子中,这很重要,因为“任何”测试可能非常昂贵,我想释放处理器以执行其他任务。
最佳答案
不幸的是,其他线程不会立即“让步”。
尽快Any()
找到有效元素,PLINQ 调度程序将停止调度新线程以检查新元素。任何现有的分区程序也将收到取消请求,这将阻止这些分区调用 Any()
在另一个项目上。
但是,当前正在执行 lambda 表达式的任何线程在您的Any()
方法仍将执行,因为他们无法知道另一个线程已经成功。它将阻止新线程调用 Any()
,但不取消“非常昂贵”委托(delegate)中的所有委托(delegate)。
旁注:
PLINQ 与 LINQ to Objects 不同,它并不真正使用延迟执行。当您调用 AsParallel()
在 IEnumerable<T>
上, ParallelQuery<T>
生成的实际上将开始并行处理您的例程。延迟执行会显着降低 PLINQ 的效率,因为如果不提前创建工作分区器和调度,就不可能进行并行调度。
编辑:
考虑之后 - 如果您的 lambda 非常昂贵,您可能需要考虑使用 CancellationToken .我在博客上详细介绍了 how cancellation in PLINQ works .通常,您只需使用 token 并调用 ThrowIfCancellationRequested() - 但是,您也可以使用 CancellationToken 并检查 IsCancellationRequested ,这将使您的 lambda“提前退出”,为您提供一种更快停止后台处理的方法......
关于c# - PLINQ延迟执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2403826/