Preface
A classmate asked this question caused by a question in the WeChat group: How many ways are there to implement C# asynchronous? If you want to know how many ways to implement C# asynchronous, we must first know the three modes of performing asynchronous operations provided by .NET, and then understand the way to implement C# asynchronously.
.NET asynchronous programming mode
.NET provides three modes for performing asynchronous operations:
Task-based asynchronous mode (TAP), which uses a single method to represent the start and completion of an asynchronous operation. TAP was introduced in .NET Framework 4. This is the recommended way to perform asynchronous programming in .NET. The async and await keywords in C# and the Async and Await operators in Visual Basic add language support for TAP. For more information, see Task-Based Asynchronous Mode (TAP).
Event-based asynchronous mode (EAP), is an old event-based model that provides asynchronous behavior. This pattern requires methods with Async suffix, as well as one or more events, event handler delegate types, and EventArg derived types. EAP was introduced in .NET Framework 2.0. It is recommended that this model be no longer used in new developments. For more information, see Event-Based Asynchronous Mode (EAP).
Asynchronous Programming Model (APM) mode (also known as the IAsyncResult mode), an old model that provides asynchronous behavior using the IAsyncResult interface. In this mode, synchronous operations require Begin and End methods (for example, BeginWrite and EndWrite to implement asynchronous write operations). This mode is not recommended for new developments. For more information, see Asynchronous Programming Model (APM).
Four ways to implement C# asynchronous
1. Asynchronous method (Async Method TAP mode)
Use the async/await keyword to implement asynchronous programming, which is a relatively commonly used asynchronous implementation method. For example:
public async Task TestDoSomeAsync() { await (1000*10); ("Async method completed."); }
2. Task Parallel Library (TPL, Task Parallel Library TAP mode)
Asynchronous programming is implemented through the Task and Task<T> types, multiple core processors can be used to perform multiple independent tasks concurrently. For example:
public static void TestTaskParallel() { var task1 = (() => { ("Task 1 completed."); }); var task2 = (() => { ("Task 2 completed."); }); Task<int> task3 = (() => { ("Task 3 completed."); return 20;// Return an integer value }); //Waiting for all tasks to complete (task1, task2, task3); }
3. Asynchronous Programming Model (APM mode)
is a classic asynchronous programming mode that requires manual creation of callback functions to handle notifications of completion or errors. It can be implemented through the Begin and End methods of the IAsyncResult design pattern, where the Begin method starts asynchronous operation, and the End method executes when the asynchronous operation is completed and returns the result of the asynchronous operation.
It should be noted that the APM mode uses the IAsyncResult interface to store the status and results of asynchronous operations, which is relatively complex and has a large amount of code. At the same time, when using APM mode, you also need to manually handle detailed work such as callback functions and waiting for asynchronous operations to be completed, making development relatively cumbersome.
class Program { static void Main(string[] args) { // Create an asynchronous operation class instance MyAsyncClass asyncClass = new MyAsyncClass(); // Start asynchronous operation IAsyncResult result = (null, null); // The main thread performs other operations // Wait for the asynchronous operation to complete and get the result int res = (result); // Handle the results of asynchronous operations ("Result: " + res); (); } } class MyAsyncClass { /// <summary> /// Method of asynchronous execution /// </summary> /// <param name="callback">callback</param> /// <param name="state">state</param> /// <returns></returns> public IAsyncResult BeginDoWork(AsyncCallback callback, object state) { // Create a new asynchronous operation object MyAsyncResult result = new MyAsyncResult(state); // Start asynchronous operation Thread thread = new Thread(() => { try { // Perform some operations int res = 1 + 2; // Set the results of asynchronous operations = res; // Trigger callback function callback?.Invoke(result); } catch (Exception ex) { // Set exceptions for asynchronous operation = ex; // Trigger callback function callback?.Invoke(result); } }); (); // Return asynchronous operation object return result; } /// <summary> /// Method to end asynchronous execution /// </summary> /// <param name="result">result</param> /// <returns></returns> public int EndDoWork(IAsyncResult result) { // Convert IAsyncResult to MyAsyncResult type and wait for the asynchronous operation to complete MyAsyncResult myResult = (MyAsyncResult)result; (); // Throw an exception in asynchronous operation if ( != null) { throw ; } // Return the result of an asynchronous operation return ; } } class MyAsyncResult : IAsyncResult { public bool IsCompleted => (0); public WaitHandle AsyncWaitHandle { get; } = new ManualResetEvent(false); public object AsyncState { get; } public bool CompletedSynchronously => false; public int Result { get; set; } /// <summary> ///Storing the results or exception information of asynchronous operations /// </summary> public Exception Error { get; set; } /// <summary> /// Constructor /// </summary> /// <param name="asyncState">asyncState</param> public MyAsyncResult(object asyncState) { AsyncState = asyncState; } }
4. Event-based Asynchronous Pattern (EAP mode)
An outdated asynchronous programming mode that requires the use of events to implement asynchronous programming. For example:
It should be noted that the EAP mode implements asynchronous programming through events, which is more concise and easy to understand than the APM mode, and also avoids detailed work such as manual processing of callback functions. However, the EAP mode does not support the async/await asynchronous keyword, so it may not be flexible enough in some specific scenarios.
public class MyAsyncClass : Component { /// <summary> /// Declare a delegate type to define the method signature of asynchronous operations /// </summary> /// <param name="arg"></param> /// <returns></returns> public delegate int MyAsyncDelegate(int arg); /// <summary> /// Declare an event to notify the completion of an asynchronous operation /// </summary> public event MyAsyncDelegate OperationNameCompleted; /// <summary> /// Asynchronous execution method, accepting a parameter arg /// </summary> /// <param name="arg"></param> public void DoWorkAsync(int arg) { // Put asynchronous operations into thread pool to execute (new WaitCallback(DoWork), arg); } /// <summary> /// Real asynchronous operation /// </summary> /// <param name="obj"></param> private void DoWork(object obj) { int arg = (int)obj; int res = arg + 1; // Trigger event, passing the result of asynchronous operation OperationNameCompleted?.Invoke(res); } }
Summary of use
Based on the above three modes of performing asynchronous operations, the following conclusions are drawn: TAP is suitable for simple parallel scenarios, EAP is more suitable for clear control of multi-terminal asynchronous scenarios with back and forth, and APM is more suitable for controlling and solving the return value of complex structures. Each has various convenient places and different areas of expression difficulties. Some methods seem troublesome, but their ideas are clear and easy to debug. Some methods seem simple, but they are puzzling to understand with interactive communication. It doesn’t mean that new ones must be good, but the right method is the best.
This is the end of this article about the detailed explanation of asynchronous in C#. For more related C# asynchronous content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!