技術(shù)頻道導(dǎo)航
HTML/CSS
.NET技術(shù)
IIS技術(shù)
PHP技術(shù)
Js/JQuery
Photoshop
Fireworks
服務(wù)器技術(shù)
操作系統(tǒng)
網(wǎng)站運(yùn)營(yíng)

贊助商

分類目錄

贊助商

最新文章

搜索

實(shí)例顯示C# Task.WhenAll與Parallel.ForEach的使用差異

作者:admin    時(shí)間:2023-6-7 11:42:11    瀏覽:

C#里 Task.WhenAllParallel.ForEach 都是實(shí)現(xiàn)多個(gè)并發(fā)任務(wù)執(zhí)行的一種方式。但是有一些不同之處,這些差異指定了它們各自適合的使用位置。

在比較它們差異之前,讓我們先簡(jiǎn)單了解一下 Task.WhenAllParallel.ForEach 的概述。

Task.WhenAll 方法

定義

  • 命名空間:System.Threading.Tasks
  • 集合:System.Runtime.dll

創(chuàng)建一個(gè)任務(wù),該任務(wù)將在所有提供的任務(wù)完成后完成。

重載

WhenAll(IEnumerable<Task>) 創(chuàng)建一個(gè)任務(wù),該任務(wù)將在可枚舉集合中的所有Task對(duì)象完成時(shí)完成。
WhenAll(Task[]) 創(chuàng)建一個(gè)任務(wù),該任務(wù)將在數(shù)組中的所有Task對(duì)象完成時(shí)完成。
WhenAll<TResult>
(IEnumerable<Task<TResult>>)
創(chuàng)建一個(gè)任務(wù),該任務(wù)將在可枚舉集合中的所有Task<TResult>對(duì)象完成時(shí)完成。
WhenAll<TResult>(Task<TResult>[]) 創(chuàng)建一個(gè)任務(wù),該任務(wù)將在數(shù)組中的所有Task<TResult>對(duì)象完成時(shí)完成。

Parallel.ForEach 方法

定義

  • 命名空間:System.Threading.Tasks
  • 集合:System.Threading.Tasks.Parallel.dll

執(zhí)行一個(gè)foreach(Visual Basic 中的 For Each )操作,其中迭代可以并行運(yùn)行。

重載

ForEach<TSource,TLocal>(IEnumerable<TSource>,
ParallelOptions, Func<TLocal>,
Func<TSource,ParallelLoopState,TLocal,TLocal>,
Action<TLocal>)
使用IEnumerable上的線程本地?cái)?shù)據(jù)執(zhí)行foreach(Visual Basic 中的For Each)操作,其中迭代可以并行運(yùn)行,可以配置循環(huán)選項(xiàng),并且可以監(jiān)視和操作循環(huán)的狀態(tài)。
ForEach<TSource,TLocal>(IEnumerable<TSource>,
ParallelOptions, Func<TLocal>,
Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>,
Action<TLocal>)
在IEnumerable上使用線程本地?cái)?shù)據(jù)和 64 位索引執(zhí)行foreach(Visual Basic 中的For Each)操作,其中迭代可以并行運(yùn)行,可以配置循環(huán)選項(xiàng),并且可以監(jiān)視和操作循環(huán)的狀態(tài)。
ForEach<TSource,TLocal>(IEnumerable<TSource>,
Func<TLocal>,
Func<TSource,ParallelLoopState,TLocal,TLocal>,
Action<TLocal>)
使用IEnumerable上的線程本地?cái)?shù)據(jù)執(zhí)行foreach(在Visual Basic 中的For Each)操作,其中迭代可以并行運(yùn)行,并且可以監(jiān)視和操作循環(huán)的狀態(tài)。
ForEach<TSource,TLocal>(IEnumerable<TSource>,
Func<TLocal>,
Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>,
Action<TLocal>)
使用IEnumerable上的線程本地?cái)?shù)據(jù)執(zhí)行foreach(Visual Basic 中的For Each)操作,其中迭代可以并行運(yùn)行,并且可以監(jiān)視和操作循環(huán)的狀態(tài)。

Task.WhenAll與Parallel.ForEach的差異

我想從一個(gè)示例開(kāi)始來(lái)描述Task.WhenAllParallel.ForEach的差異。假設(shè)我們有一個(gè)方法,該方法由一個(gè) HTTP 調(diào)用和一個(gè)存儲(chǔ)在數(shù)據(jù)庫(kù)中的命令組成。我們想同時(shí)執(zhí)行這個(gè)請(qǐng)求的多個(gè)任務(wù)。

public async Task Foo(Request request)
{            
    var result = await httpService.Send(request);
           
    await repository.Store(result);
}

因此,為了同時(shí)執(zhí)行 Foo 方法的多個(gè)調(diào)用,我們可以在 .Net Core 中使用這些方法:

Parallel.ForEach(requests, async request =>
{
    using (var sendScope = service.CreateScope())
    {
        var callService = sendScope.ServiceProvider.GetRequiredService<ICallService>();
        await callService.Foo(request);
    }
});

此外,可以使用 Task.WhenAll 來(lái)執(zhí)行此操作:

var tasks = requests.Select(async request =>
{
    using (var sendScope = service.CreateScope())
    {
        var callService = sendScope.ServiceProvider.GetRequiredService<ICallService>();
        await callService.Call(request);
    }
});
await Task.WhenAll(tasks);

我已經(jīng)在我的筆記本電腦上執(zhí)行了它們,我從不同的執(zhí)行中捕獲了這些結(jié)果:

 Task.WhenAll與Parallel.ForEach的執(zhí)行速度比較
左側(cè)每個(gè)數(shù)字 100–15000 顯示并發(fā)任務(wù)數(shù)

上圖顯示了 Foo 方法指定數(shù)量的并行任務(wù)執(zhí)行需要多長(zhǎng)時(shí)間,以毫秒為單位。

上面的執(zhí)行結(jié)果有兩個(gè)重點(diǎn):

  • 首先,與 Task.WhenAll 相比,Parallel.ForEach 的執(zhí)行時(shí)間更快。
  • 第二點(diǎn)是當(dāng)并發(fā)任務(wù)超過(guò)8000時(shí),Parallel.ForEach遇到失敗狀態(tài)。

結(jié)論

總而言之,雖然 Parallel.ForEach 具有更快的執(zhí)行時(shí)間,但 Task.WhenAll 具有更高的可擴(kuò)展性。這意味著通過(guò)增加請(qǐng)求負(fù)載,Task.WhenAll 可以毫無(wú)故障地處理它。

不要混淆可擴(kuò)展性和速度,雖然 Parallel.ForEach 在速度上更好,但與 Task.WhenAll 相比可擴(kuò)展性較低,無(wú)法響應(yīng)高負(fù)載的并發(fā)請(qǐng)求。

這個(gè)結(jié)果來(lái)自于 Task.WhenAll 旨在處理具有更高可擴(kuò)展性的并發(fā) I/O 綁定任務(wù),因?yàn)樗褂卯惒椒亲枞绞焦蚕砭€程來(lái)處理并發(fā)請(qǐng)求。

但是,另一方面,Parallel 本身是同步的。因此,在 CPU 綁定邏輯中使用它以獲得更好的性能是有益的。

相關(guān)文章

標(biāo)簽: Task.WhenAll  foreach  for  Parallel.For  Parallel.ForEach  
x
  • 站長(zhǎng)推薦
/* 左側(cè)顯示文章內(nèi)容目錄 */