Async / Await — Async Programming Basics

লেসন ১০ / ৫০

কেন Async?

I/O bound কাজ (DB, HTTP, file) এ thread block না করে অন্য কাজ করতে দেয় — server অনেক বেশি request handle করে।

Sync vs Async

// ❌ Sync — thread block
public string FetchData() {
    var client = new HttpClient();
    return client.GetStringAsync("https://api...").Result;
}

// ✅ Async
public async Task<string> FetchDataAsync() {
    var client = new HttpClient();
    return await client.GetStringAsync("https://api...");
}

Task ও Task<T>

// Task — void async
public async Task SaveAsync() {
    await db.SaveChangesAsync();
}

// Task<T> — return value
public async Task<User> GetUserAsync(int id) {
    return await db.Users.FindAsync(id);
}

// Caller
var user = await GetUserAsync(1);

Multiple Async Operations

// Sequential (slow)
var user = await GetUserAsync(1);
var orders = await GetOrdersAsync(user.Id);

// Parallel (fast) — independent calls
var userTask = GetUserAsync(1);
var productsTask = GetProductsAsync();
await Task.WhenAll(userTask, productsTask);
var user = userTask.Result;
var products = productsTask.Result;

// Task.WhenAny — first to finish
var done = await Task.WhenAny(task1, task2, task3);

Task.Delay (Timer)

await Task.Delay(2000);    // 2 sec wait, thread block না

Cancellation

public async Task<Data> FetchAsync(CancellationToken ct) {
    await Task.Delay(5000, ct);    // ct.IsCancellationRequested check
    return new Data();
}

var cts = new CancellationTokenSource();
cts.CancelAfter(3000);    // 3 sec পর cancel
try {
    await FetchAsync(cts.Token);
}
catch (OperationCanceledException) {
    Console.WriteLine("Cancelled");
}

Exception in Async

try {
    var data = await FetchAsync();
}
catch (HttpRequestException ex) {
    Console.WriteLine(ex.Message);
}

⚠️ Common Pitfalls

  • .Result বা .Wait() — deadlock এর কারণ। সবসময় await ব্যবহার করুন।
  • async void — শুধু event handler-এ। অন্যত্র async Task দিন।
  • ConfigureAwait(false) — library code এ context capture বন্ধ।

ASP.NET Core Example

[HttpGet("{id}")]
public async Task<ActionResult<User>> GetUser(int id) {
    var user = await _db.Users.FindAsync(id);
    if (user == null) return NotFound();
    return user;
}