Task คืออะไร?
Task แทนการทำงานแบบ Asynchronous (ไม่บล็อก Thread หลัก) ใน .NET ใช้สำหรับ Parallel Programming, Async/Await, และ Background Work
วิธีสร้างและเริ่ม Task
1. Task.Run() - วิธีที่ง่ายและแนะนำมากที่สุด
using System;
using System.Threading.Tasks;
public class Example {
public static void Main() {
// เริ่ม Task ทันที บน Thread Pool
Task task = Task.Run(() => {
int a = 0;
for (a = 0; a <= 1000; a++) { }
Console.WriteLine("{0} loop iterations ends", a);
});
task.Wait(); // รอให้ Task เสร็จ (Blocking)
Console.WriteLine("Main thread continues...");
}
}
2. Task Factory
// เริ่มทันที
Task.Factory.StartNew(() => {
Console.WriteLine("Welcome from Task Factory!");
});
// หรือสร้างแล้ว Start แยก
Task task = Task.Factory.StartNew(() => DoWork());
3. Constructor + Start() (Legacy)
// ใช้ Delegate
Task t = new Task(delegate { PrintMessage(); });
t.Start();
// ใช้ Lambda
Task t = new Task(() => PrintMessage());
t.Start();
Async/Await Pattern (Modern Best Practice)
using System;
using System.Threading.Tasks;
public class AsyncDemo {
// Async Method - คืนค่า Task
public static async Task DownloadDataAsync(string url) {
using (var client = new HttpClient()) {
string result = await client.GetStringAsync(url);
return result;
}
}
public static async Task Main() {
// เรียก Async Method ด้วย await
string data = await DownloadDataAsync("https://api.example.com/data");
Console.WriteLine(data);
// รันหลาย Task พร้อมกัน (Parallel)
var task1 = DownloadDataAsync("url1");
var task2 = DownloadDataAsync("url2");
var task3 = DownloadDataAsync("url3");
// รอทั้งหมดเสร็จ
string[] results = await Task.WhenAll(task1, task2, task3);
// หรือรอตัวไหนตัวนึงเสร็จ
Task first = await Task.WhenAny(task1, task2, task3);
}
}
Task Combinators (จัดการหลาย Task)
| Method |
คำอธิบาย |
Task.WhenAll(tasks) |
รอให้ Task ทุกตัวเสร็จ - คืน Array ของผลลัพธ์ |
Task.WhenAny(tasks) |
รอให้ Task ตัวไหนตัวนึงเสร็จ - คืน Task ที่เสร็จก่อน |
Task.WaitAll(tasks) |
Blocking Wait ทั้งหมด (ไม่แนะนำใน UI Thread) |
Task.WaitAny(tasks) |
Blocking Wait ตัวไหนตัวนึง |
Task.Delay(ms) |
สร้าง Task ที่เสร็จหลัง Delay (แทน Thread.Sleep) |
Task.FromResult(value) |
สร้าง Task ที่เสร็จแล้วพร้อมผลลัพธ์ |
Task Status และ Exception Handling
Task task = Task.Run(() => {
throw new InvalidOperationException("Error!");
});
try {
task.Wait(); // จะโยน AggregateException
} catch (AggregateException ex) {
foreach (var inner in ex.InnerExceptions) {
Console.WriteLine(inner.Message);
}
}
// หรือใช้ await (Unwrap Exception อัตโนมัติ)
try {
await task;
} catch (InvalidOperationException ex) {
Console.WriteLine(ex.Message); // จับได้โดยตรง
}
Task vs Thread
| คุณสมบัติ |
Task |
Thread |
| Abstraction Level |
High (Work Item) |
Low (OS Thread) |
| Thread Pool |
ใช้ Thread Pool อัตโนมัติ |
สร้าง OS Thread ใหม่ |
| Overhead |
ต่ำมาก |
สูง (1MB Stack แต่ละ Thread) |
| Return Value |
Task<T> รองรับ Result |
ต้องใช้ Callback/Shared State |
| Exception Handling |
AggregateException / await Unwrap |
Manual |
| Cancellation |
CancellationToken Built-in |
Manual Flag |
Best Practices
- ใช้
Task.Run() สำหรับ CPU-bound Work
- ใช้
async/await สำหรับ I/O-bound Work
- หลีกเลี่ยง
.Result และ .Wait() (Deadlock Risk)
- ใช้
CancellationToken สำหรับยกเลิกงาน
ConfigureAwait(false) ใน Library Code