[英]Differences between Parallel.ForEach and await ForEachAsync
在任何情況下,是否有任何理由選擇Parallel.ForEach而不是等待ForEachAsync(反之亦然)? 還是它們幾乎相同?
await collection.ForEachAsync( m => { m.DoSomething(); } );
VS
Parallel.ForEach( collection, m => { m.DoSomething(); } );
它們根本不是“幾乎相同”的。
當您使用Parallel類中的函數Parallel.ForEach()
例如Parallel.ForEach()
您正在調用某些操作,該操作分為多個較小的操作,每個操作在不同的線程(又稱為多線程)上執行。
ForEachAsync
,另一方面不一定多線程。 它是異步的,並且異步操作不是多線程的(它們可以,但不一定是,這取決於實現)。
我強烈建議閱讀以下帖子 ,其中將詳細介紹該主題。
至於你的問題
在任何情況下是否有任何理由選擇Parallel.ForEach而不是等待ForEachAsync
答案是絕對肯定有這樣做的理由,但是為了確定您將使用哪種方案,您必須同時了解它們。
這是一個簡單的例子:
您有一組對象,並且想要對其進行迭代並執行某種操作。 您是否關心這些動作的發生順序? 如果是這樣,請不要使用Parallel.ForEach()
因為不能保證調用它們的順序(由於其多線程性質)。
編輯:
在您的示例中,這全都取決於collection
有多少項以及多處理DoSomething()
程度。
這樣做的原因是因為Parallel.ForEach()
不是free 。 需要權衡取舍。 設置多線程環境會花費一些時間,並且如果collection
很小並且/或者DoSomething()
不會花費太長時間,那么設置這些線程所花費的時間會比使用單線程異步時更好(通常更快)。操作。
另一方面,如果collection
量很大和/或DoSomething()
是一個繁重的任務,則Parallel.ForEach()
將絕對是性能最高的選項。
一切都取決於線程,假設您有以下課程
public class person
{
public int ID { get; set; }
public string Name { get; set; }
}
這是你的主要班級
List<person> persons = new List<person>()
{
new person{ ID = 1,Name="Ali"}
,new person{ ID = 2,Name="Gorge"}
,new person{ ID = 3,Name="Alex"}
,new person{ ID = 4,Name="Liz"}
,new person{ ID = 5,Name="Scott"}
,new person{ ID = 6,Name="Abby"}
,new person{ ID = 7,Name="Sarah"}
};
Parallel.ForEach(persons, (p) =>
{
Console.WriteLine($"Id : {p.ID} ,Name : {p.Name}");
});
當您運行此代碼時,列表項將通過diff線程拆分,並且代碼不會按順序運行,如您在以下輸出中看到的那樣,我得到的打印順序與原始List的diff順序相同
在這里我再次運行相同的代碼,但是我得到了差異結果
由於線程的原因,編譯器將線程划分為多個,並且每個列表都運行分配給它的項,下圖顯示了diff線程
但是當您運行以下代碼時
List<person> persons = new List<person>()
{
new person{ ID = 1,Name="Ali"}
,new person{ ID = 2,Name="Gorge"}
,new person{ ID = 3,Name="Alex"}
,new person{ ID = 4,Name="Liz"}
,new person{ ID = 5,Name="Scott"}
,new person{ ID = 6,Name="Abby"}
,new person{ ID = 7,Name="Sarah"}
};
await persons.ForEachAsync(async p => Console.WriteLine($"Id : {p.ID} ,Name : {p.Name}"));
你只有一個線程顯示在這里
再加上數據打印將始終按照列表的相同順序運行
我希望這個答案能解釋差異!
在任何情況下,是否有任何理由選擇Parallel.ForEach而不是等待ForEachAsync(反之亦然)?
Parallel.ForEach
用於同步代碼。 它的委托必須是同步的,並且必須被同步調用。
ForEachAsync
不是標准算法。 有幾種不同的實現,但是通常它們會嘗試將異步和並行性混合在一起。 他們必須放棄一些Parallel.ForEach
的自我平衡方面。 絕大多數代碼不需要ForEachAsync
; 大多數代碼是異步或平行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.