3

我工作的一些非常基本的TPL代碼,我碰到的情況跑,我很好奇,如果下面的兩個片段是相同的:這兩個代碼片段是否使用IQueryable和.AsParallel等效?

myEnumerable.AsParallel().Select(e => 
{ 
    //do some work that takes awhile 
    return new Thing(e); 
} 

myEnumerable.Select(e => 
{ 
    //do some work that takes awhile 
    return new Thing(e); 
}.AsParallel() 

而且 - 如果是這樣,實際上就相當於是他們的等價的東西,可以改變TPL接口與IEnumerable擴展方法定義?或者當我更新到.NET V {無論}時,我是否設置自己來破解我的代碼?

對於背景,myEnumerable是我還沒有枚舉(做數據庫往返)的EF表(實體)。

我期望的行爲是對是同步的數據庫調用,得到一個列表,並在並行列表操作(請一堆Web服務對平行的名單打電話)

+0

小心解釋downvote所以我可以改善這個問題? – Codeman

回答

5

我很好奇,如果下面的兩個片段是等價

不,他們不是。您以前的代碼將嘗試IEnumerable進行分區以便並行執行。您後面的代碼將按順序將元素投影到您的Select,並接收已過濾的IEnumerable。只有在AsParallel後纔會並行運行。

請注意,LINQ-To-Entities實際上並不適用於AsParallel。通常,它會導致您的代碼運行速度較慢,然後順序執行。另外,DbContext不是線程安全的。該代碼可能會導致更多的傷害,然後再行善。

你可以做的是首先查詢數據庫,一旦數據在內存中,使用AsParallel

我期望的行爲是對是同步的數據庫調用,獲得 列表返回,並在並行列表操作(請一幫網對平行名單 服務調用)

如果您想通過返回的數據進行多個Web服務調用,則可以利用存在的自然異步API來發出此類請求。例如,如果您要查詢HTTP端點,則可以利用HttpClient並將其與async-await結合使用,並且可以同時執行查詢,而無需任何額外的線程。

+0

不幸的是,我沒有異步的等待可用(hooray遺留系統和古老的編碼標準),但我可能能夠湊齊一些能夠像那樣工作的東西。我會給它一個鏡頭,並在幾分鐘內更新,謝謝! – Codeman

+0

您正在使用哪種版本的.NET框架? –

+0

4.0,但我不允許使用異步/等待,因爲經理擔心未來的工程師不會理解它是如何工作的。 – Codeman

2

僅會發生什麼在AsParallel之後是平行的。它之前的所有內容都只是並行查詢的順序輸入流(例外:如果輸入已經是並行查詢,它將被視爲這樣)。

PLINQ無法並行化現有的查詢,因爲它無法對其進行解析。輸入是不透明的IEnumerable

我期望的行爲是對是同步的數據庫調用,得到一個列表,並在並行

使用在列表中操作第一代碼段。

使並行

的TPL是選擇並行的IO密集型任務的最佳程度上可怕的名單一堆Web服務調用。使用WithDegreeOfParallelism爲您的特定IO負載選擇適當的DOP。

+0

我不相信我在使用PLINQ - 只是LINQ實體。除非PLINQ在使用TPL時免費贈送? – Codeman

+1

@ Pheonixblade9 PLINQ代表「並行LINQ」,它使用TPL(任務並行庫)實現。當你使用'AsParallel'時。你正在使用PLINQ。 –

+0

我知道PLINQ是什麼:)我只是不知道它是否在使用TPL時自動出現。謝謝! – Codeman

2

不,它們不是等價的。

第一個表達式在消耗時將並行運行Select中的工作。

第二個表達式將在一個線程中運行Select中的工作,以生成並行執行的項目。你做什麼來消費第二個表達式將並行運行,但這可能是一些微不足道的事情,不會從並行中獲益。