SoFunction
Updated on 2025-04-17

Async await asynchronous keyword usage and the underlying principle of asynchronous in C#

C# asynchronous programming

1. Basics of asynchronous programming

What is asynchronous programming

  • It is to let the program be freed up the thread to do other tasks while waiting for certain time-consuming operations (such as waiting for network responses, reading and writing files, etc.), so that the program can be more sensitive and efficient.
  • Unlike synchronous programming, synchronous programming is to wait for the operation to be completed before continuing to move downwards. The threads are always occupied, which is so wasteful.

Benefits of asynchronous programming

  • Fast response:For example, when making UI interfaces, if you use asynchronous programming, the interface will not get stuck, and the user experience is amazing.
  • Save resources: No need to let the threads keep working and waiting, the resource utilization rate will increase.
  • Can carry more work: When facing a lot of concurrent operations, asynchronous programming can be easily handled, with excellent scalability.

2. Working principle of asynchronous methods

How did the asynchronous method be compiled

  • You write itasyncThe compiler turns it into a state machine by modifying it.
  • Status opportunity according toawaitThe expression breaks the method into many states, just like playing puzzles.

How does the state machine work

  • A state machine is a class generated by the compiler, and it has to remember where the asynchronous method is executed.
  • The core isMoveNextMethod, it is like a director, directing asynchronous operations step by step.
  • Every time I encounter oneawait, just switch the state.

awaitHow is the underlying implementation

  • awaitJust create a waiter, waiting specifically for the asynchronous operation to be completed.
  • If the operation is not finished yet,awaitJust record the current status and continue to move down after the operation is finished.

3. Code examples

useHttpClientDry asynchronous network requests

  • Get oneHttpClientObject, used to send HTTP requests.
  • useGetStringAsyncMethod, you can get the web page content of the specified URL asynchronously.
  • Print out the contents you got and take a look at the results.
using System;
using ;
using ;
namespace asyncawaitprinciple1
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using (HttpClient httpClient = new HttpClient())
            {
                string html = await ("");
                (html);
            }
        }
    }
}

Asynchronous reading and writing files

  • useMethod, can write text asynchronously to a file with a specified path.
  • useMethods can read the file content asynchronously.
  • Print out what you read and see if it is right.
using System;
using ;
using ;
namespace asyncawaitprinciple1
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string txt = "hello world";
            string filename = @"E:\temp\";
            await (filename, txt);
            ("Writing successfully");
            string s = await (filename);
            ("File Content:" + s);
        }
    }
}

4. Compiled underlying implementation

Decompile DLL files with ILSpy

  • ILSpy is a decompilation tool that can turn DLL files back into C# code for easy research.
  • Load the DLL file into ILSpy and you will see the compiled code.
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0 : IAsyncStateMachine
{
    public int <>1__state;
    public AsyncTaskMethodBuilder <>t__builder;
    public string[] args;
    private string <>s__1;
    private string <>s__3;
    private string <>s__6;
    private HttpClient <httpClient>__4;
    private string <html>__5;
    private string <txt>__2;
    private string <filename>__7;
    private void MoveNext()
    {
        int num = this.<>1__state;
        try
        {
            TaskAwaiter<string> awaiter;
            TaskAwaiter awaiter2;
            switch (num)
            {
                default:
                    this.<httpClient>__4 = new HttpClient();
                    goto case 0;
                case 0:
                    try
                    {
                        awaiter = this.<httpClient>__4.GetStringAsync("").GetAwaiter();
                        if (!)
                        {
                            num = this.<>1__state = 0;
                            this.<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
                            return;
                        }
                    }
                    catch (Exception exception)
                    {
                        this.<>1__state = -2;
                        this.<>t__builder.SetException(exception);
                        return;
                    }
                    this.<html>__5 = ();
                    (this.<html>__5);
                    this.<txt>__2 = "hello yz";
                    this.<filename>__7 = @"E:\temp\";
                    awaiter2 = (this.<filename>__7, this.<txt>__2).GetAwaiter();
                    if (!)
                    {
                        num = this.<>1__state = 1;
                        this.<>t__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref this);
                        return;
                    }
                    break;
                case 1:
                    awaiter2 = this.<>s__1;
                    this.<>s__1 = null;
                    num = this.<>1__state = -1;
                    break;
            }
            ();
            ("Writing successfully");
            this.<>s__3 = null;
            awaiter = (this.<filename>__7).GetAwaiter();
            if (!)
            {
                num = this.<>1__state = 2;
                this.<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
                return;
            }
            this.<>s__6 = ();
            ("File Content:" + this.<>s__6);
            this.<>s__6 = null;
            this.<>t__builder.SetResult();
        }
        catch (Exception exception)
        {
            this.<>1__state = -2;
            this.<>t__builder.SetException(exception);
            return;
        }
        this.<>1__state = -1;
    }
    void ()
    {
        // This method is implemented by the compiler-generated code.
    }
    [DebuggerHidden]
    private void SetStateMachine(IAsyncStateMachine stateMachine)
    {
        this.<>t__builder.SetStateMachine(stateMachine);
    }
    void (IAsyncStateMachine stateMachine)
    {
        (stateMachine);
    }
}

Check out the compiled state machine code

  • Analyze the structure of the state machine class to see what variables are there,MoveNextWhat does the method look like?
  • LookawaiterHow to use it, how to switch status.

understandMoveNextWhat is the method

  • MoveNextIt is the engine of the state machine, which determines how to execute the asynchronous method.
  • In this method, the corresponding code will be executed according to the current state, andawaitJust pause and arrange how to continue in the future.

5. Summary

Review of the asynchronous method compilation process

  • Talk about it againasyncHow to compile the method into a state machine, and how to calculate the state machine based on itawaitSplit method, drive asynchronous operation.

awaitWhat exactly are you doing

  • To put it bluntly,awaitIt is not really "waiting" at all, but an asynchronous collaboration achieved by state machines and waiters.
  • I would like to emphasize the benefits of asynchronous programming, such as fast response, saving resources, and being able to handle more work. What other scenarios are suitable for using it?

This is the article about the usage of async await asynchronous keywords and the underlying principles of asynchronous await in C#. For more related C# async await asynchronous keyword content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!