ใน C# มี 2 วิธีหลักสำหรับรอหลาย Task ให้เสร็จ:
| Method | Behavior | Return Type | Blocking? |
|---|---|---|---|
Task.WaitAll() |
บล็อก Thread ปัจจุบันจนกว่าทุก Task จะเสร็จ | void | Yes (Synchronous Block) |
Task.WhenAll() |
คืน Task ที่เสร็จเมื่อทุก Task เสร็จ (Non-blocking) | Task | No (Awaitable) |
ตัวอย่าง 1: Task.WhenAll (Non-blocking, แนะนำสำหรับ Async)
static async Task Main(string[] args)
{
Task task1 = Task.Run(async () =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task 1 - iteration {i}");
await Task.Delay(1000);
}
Console.WriteLine("Task 1 complete");
});
Task task2 = Task.Run(async () =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task 2 - iteration {i}");
await Task.Delay(1000);
}
Console.WriteLine("Task 2 complete");
});
Console.WriteLine("Waiting for tasks to complete (WhenAll)...");
await Task.WhenAll(task1, task2); // Non-blocking await
Console.WriteLine("Both Tasks Completed.");
}
ผลลัพธ์ (ลำดับอาจสลับเพราะรัน Parallel)
Waiting for tasks to complete (WhenAll)...
Task 1 - iteration 0
Task 2 - iteration 0
Task 1 - iteration 1
Task 2 - iteration 1
...
Task 1 complete
Task 2 complete
Both Tasks Completed.
ตัวอย่าง 2: Task.WaitAll (Blocking - ใช้ใน Console App Main แบบ Sync)
static void Main(string[] args)
{
Task task1 = Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task 1 - iteration {i}");
Thread.Sleep(1000); // Blocking sleep
}
Console.WriteLine("Task 1 complete");
});
Task task2 = Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Task 2 - iteration {i}");
Thread.Sleep(1000);
}
Console.WriteLine("Task 2 complete");
});
Console.WriteLine("Waiting for tasks to complete (WaitAll)...");
Task.WaitAll(task1, task2); // Blocking
Console.WriteLine("Both Tasks Completed.");
}
ตัวเลือกอื่นๆ
Task.WhenAny(): รอจนกว่า ใดๆ หนึ่ง จะเสร็จParallel.ForEach/Parallel.Invoke: สำหรับ CPU-bound work (ไม่ใช่ I/O async)SemaphoreSlim: จำกัดจำนวน Concurrent Tasks (Throttling)
Best Practice
- ใน Async Context (Controller, Service) ใช้
await Task.WhenAll() - ใน Entry Point แบบ Sync (Console Main) ใช้
Task.WaitAll()หรือ.GetAwaiter().GetResult() - หลีกเลี่ยง
.Resultหรือ.Wait()บน Task เดี่ยว (อาจ Deadlock)