Let’s go through async and await in C# β€” the key to asynchronous programming.


πŸ“Œ 1. What is Asynchronous Programming?

  • Asynchronous programming allows tasks to run without blocking the main thread.

  • Useful for I/O operations, web requests, file access, or database calls.

  • async and await keywords make it simple and readable compared to callbacks.


πŸ“Œ 2. async Keyword

  • Marks a method as asynchronous

  • Must return either:

    • Task β†’ for methods that return nothing

    • Task<T> β†’ for methods that return a value

    • void β†’ only for event handlers

public async Task DoWorkAsync()
{
    await Task.Delay(1000); // Simulate work
    Console.WriteLine("Work done!");
}
  • Allows awaiting asynchronous operations inside

πŸ“Œ 3. await Keyword

  • Pauses execution of the async method until the awaited task completes

  • Does not block the calling thread

public async Task MainAsync()
{
    Console.WriteLine("Start");
    await Task.Delay(2000); // Wait 2 seconds asynchronously
    Console.WriteLine("End");
}

Output:

Start
...2 seconds...
End

πŸ“Œ 4. Example: Async File Reading

using System.IO;
using System.Threading.Tasks;
 
public async Task ReadFileAsync()
{
    using StreamReader reader = new StreamReader("example.txt");
    string content = await reader.ReadToEndAsync();
    Console.WriteLine(content);
}
  • ReadToEndAsync() is non-blocking

  • Program can do other work while waiting for I/O


πŸ“Œ 5. Returning Values

public async Task<int> CalculateSumAsync(int a, int b)
{
    await Task.Delay(1000); // Simulate async operation
    return a + b;
}
 
int result = await CalculateSumAsync(5, 10);
Console.WriteLine(result); // 15
  • Use Task<T> for returning values from async methods

πŸ“Œ 6. Async with Parallel Tasks

public async Task FetchDataAsync()
{
    Task<string> task1 = Task.Run(() => "Data 1");
    Task<string> task2 = Task.Run(() => "Data 2");
 
    string[] results = await Task.WhenAll(task1, task2);
    foreach (var r in results) Console.WriteLine(r);
}
  • Task.WhenAll() waits for multiple tasks concurrently

πŸ“Œ 7. Best Practices

  1. Avoid async void except in event handlers

  2. Prefer Task or Task<T> return types

  3. Use ConfigureAwait(false) in libraries to avoid context capture

  4. Handle exceptions with try-catch inside async methods


πŸ“Œ 8. Summary Table

KeywordDescription
asyncMarks a method as asynchronous
awaitWaits for task completion without blocking
Return TypesTask, Task<T>, void (event handlers only)
Use CaseI/O, network calls, database operations
Best PracticeAvoid async void, handle exceptions, return Task

βœ… Tip:

  • Use async/await to keep your UI responsive and improve throughput in I/O-heavy applications

  • Combine with Task.WhenAll or Task.WhenAny for concurrency