Dot Net TechnologyUnit 711 min read
Multithreading & Exception Handling in C: Threads, Events, Delegates, and Error Recovery
Unit 7 of Dot Net Technology covers multithreading (thread lifecycle, synchronization, Thread and Task classes) and exception handling (try-catch-finally, custom exceptions, pre-built delegates like Func<T> and Action<T>) with real-world applications in banking, web apps, and file I/O. Includes code examples, state dia
Key Concepts and Definitions
Multithreading Basics
Thread: The smallest unit of execution within a process. A process can have multiple threads running concurrently. Process: An instance of a program in execution (e.g., a running application). Concurrency vs Parallelism:
- Concurrency: Multiple threads appear to run simultaneously (e.g., UI thread handling user input while another thread processes data).
- Parallelism: Multiple threads run truly simultaneously on multi-core CPUs.
mindmap
root((Multithreading))
Concepts
Thread: Smallest execution unit
Process: Instance of a program
Concurrency: Appearance of simultaneous execution
Parallelism: True simultaneous execution
Lifecycle
New --> Runnable --> Running --> Blocked/Waiting --> Terminated
Synchronization
Locks (lock, Monitor)
Interlocked class
Thread-safe collections
Classes
Thread
Task (TPL)
ThreadPoolThread Lifecycle in C#
The lifecycle of a thread in C# can be visualized as follows:
stateDiagram-v2 [*] --> New: Thread created but not started New --> Runnable: Start() called Runnable --> Running: Thread begins execution Running --> Blocked: Waiting for I/O or lock Running --> Waiting: Sleep() or Wait() Blocked --> Runnable: Resource available Waiting --> Runnable: Timeout or signal Running --> Terminated: Thread completes [*]
Example: Thread Lifecycle Demonstration
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread t = new Thread(PrintNumbers);
Console.WriteLine($"Thread state before start: {t.ThreadState}"); // New
t.Start();
Console.WriteLine($"Thread state after start: {t.ThreadState}"); // Runnable/Running
Thread.Sleep(1000); // Let the thread run
Console.WriteLine($"Thread state after sleep: {t.ThreadState}"); // Terminated
}
static void PrintNumbers()
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} printing: {i}");
Thread.Sleep(500); // Simulate work
}
}
}
Output Trace:
| Step | Thread State | Action | Console Output |
|---|---|---|---|
| 1 | New | Thread created | Thread state before start: New |
| 2 | Runnable/Running | t.Start() called |
Thread state after start: Running |
| 3 | Running | Thread executes PrintNumbers |
Prints numbers 1 to 5 with delays |
| 4 | Terminated | Thread completes | Thread state after sleep: Terminated |
Synchronization in Multithreading
Race Condition: Occurs when multiple threads access shared data and try to change it simultaneously, leading to unpredictable results.
Solution: Use synchronization mechanisms like lock, Monitor, or thread-safe collections.
Example: Race Condition in Bank Balance
class BankAccount
{
private int balance;
private readonly object lockObj = new object();
public void Deposit(int amount)
{
lock (lockObj)
{
balance += amount;
Console.WriteLine($"Deposited {amount}. New balance: {balance}");
}
}
public void Withdraw(int amount)
{
lock (lockObj)
{
if (balance >= amount)
{
balance -= amount;
Console.WriteLine($"Withdrew {amount}. New balance: {balance}");
}
else
{
Console.WriteLine("Insufficient balance!");
}
}
}
}
State After Each Operation:
sequenceDiagram
participant User1 as Thread 1 (Deposit)
participant User2 as Thread 2 (Withdraw)
participant Account as BankAccount
User1->>Account: Deposit(1000)
Account-->>User1: Balance: 1000 (Locked)
User2->>Account: Withdraw(500)
Account-->>User2: Balance: 500 (Locked)
User1->>Account: Deposit(200)
Account-->>User1: Balance: 700 (Locked)Exception Handling in C#
Exceptions are events that disrupt the normal flow of a program. C# provides structured exception handling using try, catch, finally, and throw.
Types of Exceptions
- System Exceptions: Built-in exceptions (e.g.,
NullReferenceException,IndexOutOfRangeException). - Application Exceptions: Custom exceptions created by developers.
Example: Handling Bank Withdrawal Exceptions
using System;
class InsufficientFundsException : Exception
{
public InsufficientFundsException(string message) : base(message) { }
}
class BankAccount
{
private decimal balance;
public BankAccount(decimal initialBalance)
{
balance = initialBalance;
}
public void Withdraw(decimal amount)
{
if (amount > balance)
{
throw new InsufficientFundsException($"Insufficient funds. Current balance: {balance}");
}
balance -= amount;
Console.WriteLine($"Withdrew {amount}. Remaining balance: {balance}");
}
}
class Program
{
static void Main()
{
BankAccount account = new BankAccount(1000);
try
{
account.Withdraw(1500); // Throws InsufficientFundsException
}
catch (InsufficientFundsException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
}
finally
{
Console.WriteLine("Transaction attempted.");
}
}
}
Output Trace:
| Step | Action | Exception Thrown | Output |
|---|---|---|---|
| 1 | account.Withdraw(1500) |
InsufficientFundsException |
Error: Insufficient funds. Current balance: 1000 |
| 2 | catch block |
- | Transaction attempted. (finally block) |
Events and Delegates in C#
Delegates
Delegates are type-safe function pointers in C#. They enable passing methods as arguments.
Generic Delegates
Action<T>: Used for methods that returnvoid.Func<T>: Used for methods that return a value.
Example: Lambda Expression with Generic Delegate
using System;
class Program
{
static void Main()
{
// Using Action<T> (void return)
Action<int> printSquare = x => Console.WriteLine($"Square of {x} is {x * x}");
printSquare(5); // Output: Square of 5 is 25
// Using Func<T> (returns int)
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine($"Sum: {add(3, 4)}"); // Output: Sum: 7
}
}
In the Real World
eSewa (Nepal):
- Multithreading: eSewa processes thousands of transactions simultaneously. Background threads handle payment validations, SMS notifications, and database updates concurrently to ensure quick responses.
- Exception Handling: Custom exceptions are thrown for invalid transactions (e.g., insufficient balance, expired card). These are logged and user-friendly messages are displayed.
Khalti (Nepal):
- Thread Pool: Khalti uses thread pools to manage multiple payment requests efficiently. For example, during Diwali sales, hundreds of users might request payments at once. Thread pools ensure these requests are processed without overwhelming the system.
- Synchronization: Shared resources like user accounts or transaction logs are protected using locks to prevent race conditions.
Pathao (Nepal):
- Multithreading: Pathao’s backend uses multithreading to handle ride requests, driver assignments, and GPS updates in parallel. For example, while one thread processes a new ride request, another thread updates the driver’s location on the map.
- Exception Handling: If a driver’s GPS signal is lost, Pathao throws a custom exception (
GpsSignalLostException) and notifies the driver to restart the app or check their connection.
NTC (Nepal Telecom):
- Task Parallel Library (TPL): NTC’s customer service portal uses
Taskfor parallel processing of bulk SMS or email notifications. For example, sending a promotional offer to 10,000 subscribers is divided into smaller tasks executed concurrently. - Custom Exceptions: If a subscriber’s number is invalid, NTC throws a
InvalidPhoneNumberExceptionand skips that number in the batch.
- Task Parallel Library (TPL): NTC’s customer service portal uses
Exam Tip
- Thread Lifecycle: Always explain the states (
New,Runnable,Running,Blocked,Terminated) with a diagram or code snippet. Examiners love seeing state transitions. - Synchronization: Use
lockin examples to prevent race conditions. ComparelockwithMonitorand explain when to use each. - Exception Handling:
- Differentiate between
try-catch-finallyandusingblocks. - Write custom exceptions with inheritance from
Exceptionand include constructors. - Handle common exceptions like
NullReferenceException,IndexOutOfRangeException, andFormatException.
- Differentiate between
- Delegates and Lambda Expressions:
- Show how
Action<T>andFunc<T>are used with lambda expressions. - Explain generic delegates with a practical example (e.g., sorting a list with a custom comparator).
- Show how
- Real-World Scenarios:
- Tie examples to banking (e.g., concurrent transactions), web apps (e.g., handling user requests), or file I/O (e.g., reading/writing logs).
- For multithreading, use
Thread.Sleep()to simulate delays and demonstrate thread interleaving.
Common Pitfalls to Avoid
- Deadlocks: Always release locks in a
finallyblock or usetry-finallyto avoid deadlocks.lock (lockObj1) { lock (lockObj2) { /* Critical section */ } } - Ignoring Exceptions: Never swallow exceptions with an empty
catchblock. At least log the error. - Thread Safety: Assume shared data is unsafe unless proven otherwise. Use
lockor thread-safe collections likeConcurrentQueue<T>.
Practice Questions for Exam
- Write a C# program to demonstrate thread synchronization using
lockfor a shared counter. - Create a custom exception
InvalidAgeExceptionand handle it in a method that validates user age. - Explain the difference between
ThreadandTaskclasses. When would you use each? - Write a program that uses
Action<T>to process a list of strings (e.g., convert to uppercase). - How would you handle a
DivideByZeroExceptionin a calculator application? Show the code.
Summary Table: Key Concepts
| Concept | Description | Example Use Case |
|---|---|---|
| Thread | Lightweight process for concurrent execution. | Pathao handling multiple ride requests. |
| Lock | Synchronization mechanism to prevent race conditions. | Bank account balance updates. |
| Exception | Event that disrupts normal flow. | Invalid user input in eSewa. |
| Delegate | Type-safe function pointer. | Event handlers in WinForms. |
| Lambda Expression | Anonymous function for concise syntax. | LINQ queries in C#. |
| Task | Higher-level abstraction for asynchronous programming. | NTC sending bulk SMS notifications. |
Based on the TU BCA syllabus for Dot Net Technology (CACS408), unit 7.
Discussion
Loading…