SoFunction
Updated on 2025-03-07

Summary of common ways to implement asynchronous C#

Preface

How many ways are there to implement C# asynchronous asynchronous this question caused by a question in the WeChat group? First of all, if you want to know how many C# asynchronous implementations are, we need to know the three modes of performing asynchronous operations provided by .NET, and then understand the way C# asynchronous implementations.

.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 method for asynchronous programming in .NET.     in C#asyncandawaitKeywords and the ones in Visual BasicAsyncandAwaitThe operator adds language support for TAP. For more information, seeTask-based asynchronous mode (TAP)
  • Event-based asynchronous mode (EAP), is an old event-based model that provides asynchronous behavior. This pattern requires the suffix asAsyncMethods, as well as one or more events, event handler delegate types andEventArgDerived type. EAP was introduced in .NET Framework 2.0. It is recommended that this model be no longer used in new developments. For more information, seeEvent-based asynchronous mode (EAP)
  • Asynchronous Programming Model (APM) mode (also known asIAsyncResultmode), this is usedIAsyncResultThe interface provides an old model of asynchronous behavior. In this mode, synchronous operations requireBeginandEndMethod (e.g.BeginWriteandEndWriteto implement asynchronous write operations). This mode is not recommended for new developments. For more information, seeAsynchronous Programming Model (APM)

There are four ways to implement C# asynchronous

There are many implementation methods for C# asynchronous, which can be summarized into the following categories:

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);
        ("Async method completed.");
    }

2. Task Parallel Library (TPL, Task Parallel LibraryTAP 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 async void Main(string[] args)
    {
        await (() =&gt;
        {
            ("Test Task 1 completed.");
        });
        await (() =&gt;
        {
            ("Test Task 2 completed.");
        });
        // Wait for all tasks to complete        ();
    }

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
    {
        /// &lt;summary&gt;
        /// Method of asynchronous execution        /// &lt;/summary&gt;
        /// &lt;param name="callback"&gt;callback&lt;/param&gt;
        /// &lt;param name="state"&gt;state&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        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(() =&gt;
            {
                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;
        }

        /// &lt;summary&gt;
        /// Method to end asynchronous execution        /// &lt;/summary&gt;
        /// &lt;param name="result"&gt;result&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        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 =&gt; (0);
        public WaitHandle AsyncWaitHandle { get; } = new ManualResetEvent(false);
        public object AsyncState { get; }
        public bool CompletedSynchronously =&gt; false;

        public int Result { get; set; }

        /// &lt;summary&gt;
        ///Storing the results or exception information of asynchronous operations        /// &lt;/summary&gt;
        public Exception Error { get; set; }

        /// &lt;summary&gt;
        /// Constructor        /// &lt;/summary&gt;
        /// &lt;param name="asyncState"&gt;asyncState&lt;/param&gt;
        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
    {
        /// &lt;summary&gt;
        /// Declare a delegate type to define the method signature of asynchronous operations        /// &lt;/summary&gt;
        /// &lt;param name="arg"&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public delegate int MyAsyncDelegate(int arg);

        /// &lt;summary&gt;
        /// Declare an event to notify the completion of an asynchronous operation        /// &lt;/summary&gt;
        public event MyAsyncDelegate OperationNameCompleted;

        /// &lt;summary&gt;
        /// Asynchronous execution method, accepting a parameter arg        /// &lt;/summary&gt;
        /// &lt;param name="arg"&gt;&lt;/param&gt;
        public void DoWorkAsync(int arg)
        {
            // Put asynchronous operations into thread pool to execute            (new WaitCallback(DoWork), arg);
        }

        /// &lt;summary&gt;
        /// Real asynchronous operation        /// &lt;/summary&gt;
        /// &lt;param name="obj"&gt;&lt;/param&gt;
        private void DoWork(object obj)
        {
            int arg = (int)obj;
            int res = arg + 1;

            // Trigger event, passing the result of asynchronous operation            OperationNameCompleted?.Invoke(res);
        }
    }

The above is the detailed summary of the common methods of C# implementing asynchronous. For more information about C# asynchronous, please pay attention to my other related articles!