C# Multithreading Journey (4): Introduction to the Asynchronous Programming Model (APM)
This article introduces the Asynchronous Programming Model (APM) in C#, demonstrating how to use delegates and BeginInvoke/EndInvoke to run time‑consuming operations concurrently, includes sample code, explains delegate generation, and discusses practical considerations such as IAsyncResult handling and callback execution.
This article is part of a series on C# multithreading and focuses on the Asynchronous Programming Model (APM). It begins with a brief background, noting that previous chapters covered basic threading concepts and that APM offers a powerful way to perform asynchronous operations using delegates.
1. Simple Serial Execution Program
A basic example defines an int Add(int num) method that simulates a time‑consuming operation. The Main method calls Add sequentially, showing that the operations run serially and highlighting the desire to execute them in parallel using APM.
2. Using Delegates to Implement APM
2.1 Prerequisite Knowledge
Understanding delegates, generic delegates, and why they are suitable for APM is essential. Delegates provide BeginInvoke and EndInvoke methods that enable asynchronous execution.
The generic delegate definition is shown below:
/// <summary>
/// 定义一个泛型委托
/// </summary>
/// <typeparam name="T">输入参数</typeparam>
/// <typeparam name="TResult">返回值</typeparam>
/// <param name="arg">输入参数</param>
/// <returns name="TResult">返回值</returns>
private delegate TResult Func<T, TResult>(T arg);The compiler turns this into a sealed class derived from MulticastDelegate, exposing methods such as Invoke, BeginInvoke, and EndInvoke:
public sealed class Func<T, TResult> : MulticastDelegate {
public Func(Object obj, IntPtr method);
public TResult Invoke(T arg);
public IAsyncResult BeginInvoke(T arg, AsyncCallback callback, Object obj);
public TResult EndInvoke(IAsyncResult result);
}2.2 How BeginInvoke and EndInvoke Work
BeginInvoke takes the delegate arguments, a callback, and a state object, returning an IAsyncResult that carries the original arguments and can be used to identify the specific call.
EndInvoke receives the IAsyncResult, blocks until the asynchronous operation completes, and returns the delegate’s result.
2.3 Sample APM Implementation
The article provides a complete code example that uses a delegate to run the Add method asynchronously, prints interleaved results from the main thread and the worker thread, and demonstrates proper handling of IAsyncResult, casting to AsyncResult, and exception handling around EndInvoke.
Key observations include:
The callback runs on a thread‑pool thread.
The object parameter of BeginInvoke can hold any data (the example passes a string).
The main thread’s loop and the asynchronous Add execute concurrently.
Calling EndInvoke before the operation finishes blocks the calling thread.
Exceptions from EndInvoke must be caught.
Finally, the author notes that this is an introductory look at APM and that future chapters will explore the model in greater depth.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
