ฉันเคยเห็น Parallel.ForEach ใช้อย่างไม่เหมาะสมและฉันคิดว่าตัวอย่างในคำถามนี้จะช่วย
เมื่อคุณเรียกใช้รหัสด้านล่างในแอปคอนโซลคุณจะเห็นว่างานที่ดำเนินการใน Parallel นั้น forEach ไม่ได้บล็อกเธรดการโทร สิ่งนี้อาจไม่เป็นไรถ้าคุณไม่สนใจผลลัพธ์ (บวกหรือลบ) แต่ถ้าคุณต้องการผลลัพธ์คุณควรใช้ Task.WhenAll
using System;
using System.Linq;
using System.Threading.Tasks;
namespace ParrellelEachExample
{
class Program
{
static void Main(string[] args)
{
var indexes = new int[] { 1, 2, 3 };
RunExample((prefix) => Parallel.ForEach(indexes, (i) => DoSomethingAsync(i, prefix)),
"Parallel.Foreach");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("*You'll notice the tasks haven't run yet, because the main thread was not blocked*");
Console.WriteLine("Press any key to start the next example...");
Console.ReadKey();
RunExample((prefix) => Task.WhenAll(indexes.Select(i => DoSomethingAsync(i, prefix)).ToArray()).Wait(),
"Task.WhenAll");
Console.WriteLine("All tasks are done. Press any key to close...");
Console.ReadKey();
}
static void RunExample(Action<string> action, string prefix)
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"{Environment.NewLine}Starting '{prefix}'...");
action(prefix);
Console.WriteLine($"{Environment.NewLine}Finished '{prefix}'{Environment.NewLine}");
}
static async Task DoSomethingAsync(int i, string prefix)
{
await Task.Delay(i * 1000);
Console.WriteLine($"Finished: {prefix}[{i}]");
}
}
}
นี่คือผลลัพธ์:
สรุป:
การใช้ Parallel.ForEach กับ Task จะไม่บล็อกเธรดการโทร หากคุณใส่ใจกับผลลัพธ์ตรวจสอบให้แน่ใจว่าได้รองาน
~ ไชโย
Task.WaitAll
Task.WhenAll