C# Async
CancellationToken
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var cts = new CancellationTokenSource(); // Create a token source
CancellationToken token = cts.Token;
Task task = DoWorkAsync(token);
// Listen for user input in a separate task
_ = Task.Run(() =>
{
while (true)
{
if (Console.KeyAvailable)
{
var key = Console.ReadKey(true).Key;
Console.WriteLine($"Key pressed: {key}");
if (key == ConsoleKey.B)
{
cts.Cancel();
break;
}
}
}
});
try
{
await task;
}
catch (OperationCanceledException)
{
Console.WriteLine("Task was canceled.");
}
}
static async Task DoWorkAsync(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested(); // Check for cancellation
Console.WriteLine($"Working... Local time: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
await Task.Delay(1000);
}
}
}
Observer pattern
In the below example, I use the observer pattern to notify multiple observers when the temperature changes. The WeatherStation
class is the subject that maintains a list of observers. The TemperatureDisplay
and AnotherTemperatureDisplay
classes are concrete observers that display the temperature. The WeatherStation
class notifies all observers when the temperature changes.
The user can increase or decrease the temperature by pressing the up and down arrow keys, respectively. The user can exit the program by pressing the Esc key.
using System;
using System.Collections.Generic;
// The Subject (WeatherStation)
public class WeatherStation
{
private List<IObserver> observers = new List<IObserver>(); // List of observers
private float temperature;
// Method to attach an observer
public void Attach(IObserver observer)
{
observers.Add(observer);
}
// Method to detach an observer
public void Detach(IObserver observer)
{
observers.Remove(observer);
}
// Method to notify all observers
public void Notify()
{
foreach (var observer in observers)
{
observer.Update(temperature); // Notify observer with the new temperature
}
}
// Method to simulate temperature change
public void SetTemperature(float temperature)
{
this.temperature = temperature;
Notify(); // Notify observers about the state change
}
}
// The Observer Interface
public interface IObserver
{
void Update(float temperature);
}
// Concrete Observer - Display 1 (Temperature Display)
public class TemperatureDisplay : IObserver
{
public void Update(float temperature)
{
Console.WriteLine($"Temperature Display: Current temperature is {temperature}°C");
}
}
// Concrete Observer - Display 2 (Another Temperature Display)
public class AnotherTemperatureDisplay : IObserver
{
public void Update(float temperature)
{
Console.WriteLine($"Another Temperature Display: Current temperature is {temperature}°C");
}
}
// Client Code
class Program
{
static void Main()
{
// Create subject (weather station)
WeatherStation weatherStation = new WeatherStation();
// Create observers (displays)
IObserver display1 = new TemperatureDisplay();
IObserver display2 = new AnotherTemperatureDisplay();
// Attach observers to the subject
weatherStation.Attach(display1);
weatherStation.Attach(display2);
float baseTemperature = 25.0f;
weatherStation.SetTemperature(baseTemperature);
while (true)
{
if (Console.KeyAvailable)
{
var key = Console.ReadKey(true).Key;
if (key == ConsoleKey.UpArrow)
{
baseTemperature += 0.5f;
weatherStation.SetTemperature(baseTemperature);
}
else if (key == ConsoleKey.DownArrow)
{
baseTemperature -= 0.5f;
weatherStation.SetTemperature(baseTemperature);
}
else if (key == ConsoleKey.Escape)
{
break;
}
}
}
}
}
Delegate
using System;
class Program
{
// Delegate definition
public delegate void GreetDelegate(string name);
// Method that matches the delegate signature
public static void GreetInEnglish(string name)
{
Console.WriteLine("Hello, " + name);
}
// Another method with a similar signature
public static void GreetInSpanish(string name)
{
Console.WriteLine("Hola, " + name);
}
static void Main()
{
// Instantiate delegate and point it to GreetInEnglish method
GreetDelegate greet = GreetInEnglish;
greet("Alice"); // Calls GreetInEnglish
// Pointing delegate to GreetInSpanish method
greet = GreetInSpanish;
greet("Bob"); // Calls GreetInSpanish
}
}
Example II, multicast
using System;
class Program
{
// Delegate definition
public delegate void NotifyDelegate();
// Methods to be called by the delegate
public static void NotifyByEmail()
{
Console.WriteLine("Notification sent via email.");
}
public static void NotifyBySMS()
{
Console.WriteLine("Notification sent via SMS.");
}
static void Main()
{
// Create a multicast delegate by combining two methods
NotifyDelegate notify = NotifyByEmail;
notify += NotifyBySMS; // Add another method to the delegate
// Calls both methods
notify();
}
}
Example III, dynamic invocation
using System;
class Program
{
// Delegate definition
public delegate int Operation(int a, int b);
// Methods to be passed to the delegate
public static int Add(int a, int b)
{
return a + b;
}
public static int Multiply(int a, int b)
{
return a * b;
}
// Method that accepts a delegate
public static void PerformOperation(int a, int b, Operation operation)
{
int result = operation(a, b);
Console.WriteLine("Result: " + result);
}
static void Main()
{
// Passing methods via delegate
PerformOperation(5, 3, Add); // Calls Add
PerformOperation(5, 3, Multiply); // Calls Multiply
}
}
Enjoy Reading This Article?
Here are some more articles you might like to read next: