2010-03-08 208 views
3

我想了解如何使用PLINQ並行性,如果延遲執行。這是一個簡單的例子。PLINQ延遲執行

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

使用LINQ,我希望執行以達到「回執」值並返回true,而不執行查詢的值的其餘部分。

如果我們同時這樣做,「救濟」的評估可能在「回執」結果返回之前就開始了。但是一旦查詢知道「收據」會產生真實結果,其他線程是否會立即產生?

在我的情況下,這很重要,因爲「any」測試可能非常昂貴,我想釋放處理器以執行其他任務。

回答

4

不幸的是,其他線程不會立即「屈服」。

只要Any()找到有效元素,PLINQ調度程序就會停止調度新線程以檢查新元素。任何現有的分區程序也將收到取消請求,這將阻止這些分區在另一個項目上調用Any()

然而,當前正在執行的內您Any()方法lambda表達式任何線程仍然會執行,因爲沒有辦法讓他們知道,另一個線程成功。它將阻止新線程調用Any(),但不會取消「非常昂貴」代表中的所有線程。

在一個側面說明:

PLINQ,不像LINQ到對象,並沒有真正使用延遲執行。在IEnumerable<T>上撥打AsParallel()時,生成的ParallelQuery<T>實際上將開始並行處理您的例程。延遲執行會大大降低PLINQ的有效性,因爲如果不提前創建工作分區和時間安排,就不可能同時進行安排。


編輯:

思考之後 - 如果你的拉姆達是非常昂貴的,你可能要考慮使用CancellationToken。我詳細地寫了一篇關於how cancellation in PLINQ works的博客。通常情況下,您只需使用令牌並致電ThrowIfCancellationRequested() - 但是,您也可以使用CancellationToken並檢查IsCancellationRequested,它可以讓您將lambda「提前退出」,從而爲您提供一種更快地停止後臺處理的方法...

+0

http://msdn.microsoft.com/en-us/library/dd997425(VS.100).aspx表示延遲執行原則仍在PLINQ中發揮作用......你能澄清一下你在你的意思方面呢? – tbischel 2010-03-08 19:17:51

+0

@tbischel:他們這樣做,他們不......這個評論有點誤導。不同之處在於,在LINQ中,每個元素只按請求執行(延遲)。在PLINQ中,只要您發出第一個請求,就會設置一個'Partitioner ',它開始將您的工作安排到多個線程。最終的累計結果直到請求才會被推回,但處理髮生在請求元素之前。 (如果您請求結果的元素1,元素1,2,3和4可能全部被調度,並立即開始「工作」......) – 2010-03-08 19:33:10