Asynchronous Programming in C# - Textnotes

Asynchronous Programming in C#


Asynchronous programming allows your application to perform multiple tasks concurrently without blocking the main thread, improving responsiveness.

1. Async & Await

  1. async keyword marks a method as asynchronous.
  2. await pauses execution until the awaited task completes.

using System;
using System.Threading.Tasks;

class Program
{
static async Task Main()
{
Console.WriteLine("Start");

await DoWorkAsync();

Console.WriteLine("End");
}

static async Task DoWorkAsync()
{
await Task.Delay(2000); // Simulate 2-second work
Console.WriteLine("Work completed asynchronously");
}
}

Output:


Start
Work completed asynchronously (after 2 seconds)
End

2. Task Parallel Library (TPL)

TPL provides high-level abstractions for multithreading.


using System;
using System.Threading.Tasks;

class Program
{
static void Main()
{
Task t1 = Task.Run(() => Console.WriteLine("Task 1 running"));
Task t2 = Task.Run(() => Console.WriteLine("Task 2 running"));

Task.WaitAll(t1, t2);
Console.WriteLine("All tasks completed");
}
}

Features of TPL:

  1. Task.Run() → Executes code asynchronously
  2. Task.WaitAll() → Wait for all tasks to complete
  3. ContinueWith() → Execute a continuation task

3. Multi-threading in C#

Create and run multiple threads.


using System;
using System.Threading;

class Program
{
static void Main()
{
Thread t1 = new Thread(() => PrintNumbers("Thread 1"));
Thread t2 = new Thread(() => PrintNumbers("Thread 2"));

t1.Start();
t2.Start();

t1.Join();
t2.Join();

Console.WriteLine("Main thread finished");
}

static void PrintNumbers(string threadName)
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine($"{threadName}: {i}");
Thread.Sleep(500);
}
}
}

4. Thread vs ThreadPool

FeatureThreadThreadPool
CreationManual (new Thread)Automatic (ThreadPool.QueueUserWorkItem)
ReuseNoYes
OverheadHighLow
Best forLong-running threadsShort tasks

Example of ThreadPool:


ThreadPool.QueueUserWorkItem(state =>
{
Console.WriteLine("ThreadPool task running");
});

5. Cancellation Tokens

Used to cancel tasks safely.


using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
static async Task Main()
{
var cts = new CancellationTokenSource();
var token = cts.Token;

var task = Task.Run(async () =>
{
for (int i = 1; i <= 10; i++)
{
token.ThrowIfCancellationRequested();
Console.WriteLine(i);
await Task.Delay(500);
}
}, token);

// Cancel after 2 seconds
await Task.Delay(2000);
cts.Cancel();

try
{
await task;
}
catch (OperationCanceledException)
{
Console.WriteLine("Task cancelled");
}
}
}

6. BackgroundWorker

Legacy way to run tasks in the background and report progress.


using System;
using System.ComponentModel;
using System.Threading;

class Program
{
static void Main()
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;

worker.DoWork += (s, e) =>
{
for (int i = 0; i <= 100; i += 20)
{
Thread.Sleep(500);
worker.ReportProgress(i);
}
};

worker.ProgressChanged += (s, e) =>
{
Console.WriteLine($"Progress: {e.ProgressPercentage}%");
};

worker.RunWorkerCompleted += (s, e) =>
{
Console.WriteLine("Background work completed");
};

worker.RunWorkerAsync();
Console.WriteLine("Main thread continues...");
Console.ReadLine();
}
}

Summary of Chapter 12:

  1. Async & Await: Simplify asynchronous method calls.
  2. Task Parallel Library: Run multiple tasks efficiently.
  3. Multi-threading: Threads run code concurrently.
  4. Thread vs ThreadPool: ThreadPool is efficient for short tasks.
  5. Cancellation Tokens: Cancel tasks safely.
  6. BackgroundWorker: Legacy approach to run background tasks with progress reporting.