Explore the async, await anatomy of C #

Source: Internet
Author: User
Tags apm new set

Read the catalogue:
    1. Basic introduction
    2. Basic analysis
    3. Internal implementation Anatomy
    4. Place to focus attention
    5. Summarize
Basic introduction

Async, await is the new asynchronous programming method of net4.x, which is designed to simplify the writing of asynchronous programs, with a simple contrast to the previous APM approach.

APM mode, BeginGetRequestStream needs to pass in the callback function, when the thread encounters beginxxx, it will continue to execute the following logic in nonblocking form, and then callback the previously passed function after completion.

    HttpWebRequest Myreq = (HttpWebRequest) webrequest.create ("http://cnblogs.com/");     Myreq.begingetrequeststream ();      //  to do

In async mode, using the async tag Async1 as an async method, the await token Getrequeststreamasync represents a time-consuming operation within the method. The main thread returns immediately when it encounters an await and continues to execute the logic below the main thread in a non-blocking form. When the await time-consuming operation is complete, proceed to the following logic ASYNC1

Static Async void Async1 ()    {        = (HttpWebRequest) webrequest.create ("http://cnblogs.com/");         await Myreq.getrequeststreamasync ();         // to do    }     

Above is the implementation of the Net class library asynchronously, if you want to implement your own method asynchronously.
APM Mode:

         Public Delegate int MyDelegate (int  x);            New return 1 ; });         Mathdel.begininvoke (1, (a) + = {},null);

Async mode:

Static Async void Async2 ()    {        await task.run (() = {Thread.Sleep (+); Console.WriteLine ("bbb");});        Console.WriteLine ("CCC");  Async2 ();  Console.WriteLine ("aaa");

Compared to the discovery, async/await is very concise and beautiful, need to write less code, more in line with people to write habits.
Because the human mind is better understood in linear steps.

The steps of the APM asynchronous callback are: a logic--false C callback logic->b logic--True C callback logic, which will cause confusion in some degree, when a large number of asynchronous callbacks appear in a project, it becomes difficult to maintain.
The addition of Async and await allows this chaotic step to be re-dialed, with the following steps: A logic->b logic->c logic.

Basic analysis

As a programmer of self-cultivation, inquisitive curiosity is very important. When async comes out, it makes people feel confused, and the await comes back directly, and Microsoft has a new set of asynchronous models. That is because of the habit of the previous APM non-linear way, now the return to the linear step instead of understanding. When learning async, you can use the existing APM approach to understand that the following code is purely fictitious .
For example, the Async2 method to visualize the Async3 method of APM mode:

Static Async void Async3 ()    {        varawait task.run (() = {Thread.Sleep (); Console.WriteLine ("bbb");});        // Callback after registering task completion        Task. Registercompletedcallback (() =        {            Console.WriteLine ("CCC") );        });    }

It is better to understand the above, and then the Async3 method to imagine the Async4 method:

Static  voidAsync4 () {varThread =NewThread (() ={Thread.Sleep ( -); Console.WriteLine ("BBB");        }); //callback after registering thread completionThread. Registercompletedcallback (() ={Console.WriteLine ("CCC");        }); Thread.    Start (); }

This looks very simple and straightforward, and even async is removed, becoming a familiar programming habit. Although the code is purely fictitious, the basic idea is the same, the difference lies in the implementation of the details above.

Internal implementation Anatomy

As a programmer of self-cultivation, rigorous and is not less than the attitude. The above basic idea although good understanding, but the concrete detail, the programming is a slightest the slightest false work, that fictitious code completely sorry crossing.

Continue to look at the Async2 method, the full code after the decompile is as follows:

Internal classprogram{//Methods[Asyncstatemachine (typeof(<Async2>d__2)), DebuggerStepThrough]Private Static voidAsync2 () {<Async2>d__2 d__; d__.<>t__builder =asyncvoidmethodbuilder.create (); d__.<>1__state =-1; d__.<>t__builder. Start<<async2>d__2> (refd__); }    Private Static voidMain (string[] args)        {ASYNC2 (); Console.WriteLine ("AAA");    Console.ReadLine (); }    //Nested Types[compilergenerated]Private struct<Async2>D__2:iasyncstatemachine {// Fields         Public int<>1__state;  PublicAsyncvoidmethodbuilder <>T__builder; Private Object<>T__stack; PrivateTaskawaiter <>U__$awaiter3; //Methods        Private voidMoveNext () {Try{Taskawaiter awaiter; BOOLFlag =true; Switch( This.<>1__state) {                     Case-3:                        Gotolabel_00c5;  Case 0:                         Break; default:                        if(Program.cs$<>9__cachedanonymousmethoddelegate1 = =NULL) {program.cs$<>9__cachedanonymousmethoddelegate1 =NewAction (program.<async2>b__0); } awaiter= Task.run (program.cs$<>9__cachedanonymousmethoddelegate1).                        Getawaiter (); if(Awaiter. iscompleted) {Gotolabel_0090; }                         This. <>1__state =0;  This. <>u__$awaiter3 =Awaiter;  This. <>t__builder. Awaitunsafeoncompleted<taskawaiter, Program.<async2>d__2> (refAwaiter,ref  This); Flag=false; return; } awaiter= This.<>U__$awaiter3;  This. <>u__$awaiter3 =NewTaskawaiter ();  This. <>1__state =-1; Label_0090:awaiter.                GetResult (); Awaiter=NewTaskawaiter (); Console.WriteLine ("CCC"); }            Catch(Exception Exception) { This. <>1__state =-2;  This.<>T__builder.                SetException (Exception); return; } LABEL_00C5: This. <>1__state =-2;  This.<>T__builder.        Setresult (); } [Debuggerhidden]Private voidsetstatemachine (Iasyncstatemachine param0) { This.<>T__builder.        Setstatemachine (PARAM0); }    }     Public Delegate intMyDelegate (intx);} Collapse Methods
View Code

Async, await is missing, it is the compiler level provided by the syntax of sugar optimization, so that async is not considered a new asynchronous model. It can be understood that async is more of a regression of linear execution steps, specifically designed to simplify asynchronous code writing.
From the anti-compiled code to see the compiler reborn into an inherited iasyncstatemachine state machine structure ASYNCD (called <async2>d__2 in the code, followed by shorthand Asyncd), the following is based on the anti-compiled code to analyze the .

Iasyncstatemachine the most basic state machine interface definition:

 Public Interface iasyncstatemachine{    void  MoveNext ();     void setstatemachine (Iasyncstatemachine statemachine);}

Since there is no obstacle to async, await syntax sugar, the code execution process can be understood in a linear order, with the entire execution of the following steps:

1. Main thread call ASYNC2 () method
2. The Async2 () method initializes the state machine state to 1, starting ASYNCD
3. The MoveNext method is executed internally, and its task.run function is to throw the task into the thread pool and return a waiting handle to the task. MoveNext Source Analysis:

Delegate to perform the task

New Action (PROGRAM.<ASYNC2>B__0);

Getting Started with task asynchronous is the net4.0 task-based programming approach.

Awaiter =task.run (program.cs$<>9__cachedanonymousmethoddelegate1). Getawaiter ();

Set the status to 0 to MoveNext the direct break again, executing the logic behind switch, typical state machine mode.

 This 0;

Returns the thread that invokes the Async2 method, allowing it to continue executing the logic behind the main thread

this. <>t__builder. Awaitunsafeoncompleted<taskawaiter, program.<async2>d__2> (refref This ); return;

4. At this point there are already 2 threads running, namely the main thread and Task.run running task threads.

5. After executing the main thread, the logic output AAA, the task thread after the completion of the output BBB, after the task thread continues to execute the business logic output CCC.

New Taskawaiter (); Console.WriteLine ("CCC");

This can be understood as Async takes the entire main thread synchronization logic and splits it into two blocks. The first block is executed directly on the main thread, and the second block is executed after the task thread completes, and the middle of the two block is the task thread running and its source code is awaiter. GetResult () executes the second block while waiting for the task thread to complete.
From the consumer's point of view, the execution step is: main thread A logic----Asynchronous task thread B logic, the main thread C logic.

  Test (); Console.WriteLine (  a logic   " );  static  async  void   Test () { await  Ta Sk. Run (() = {Thread.Sleep (1000 ); Console.WriteLine (  " );            }); Console.WriteLine (  c logic   " ); }

To look back and compare the fictional methods in the Basic Analysis section Async4 (), the difference is that one is the completion callback, one is waiting to be completed and then executed, which is the most basic way to implement the asynchronous two categories.

The main thread of the main thread a logic----Asynchronous task thread B logic--and the mainline C logic.

Note: These 3 steps are likely to use the same thread, or you may use 2 or even 3 threads. Can be learned with the Thread.CurrentThread.ManagedThreadId test.

     Async7 ();     Console.WriteLine (Thread.CurrentThread.ManagedThreadId);      Static Async void Async7 ()    {        await task.run (() =        {            Console.WriteLine ( Thread.CurrentThread.ManagedThreadId);         });        Console.WriteLine (Thread.CurrentThread.ManagedThreadId);     }

Because of this, it will be said that Async does not have to use the thread, there is a need to say, from a single point of view are right, also is wrong. The above source code is simple analysis, the specific async internal will involve thread context switch, thread reuse, scheduling and so on. Want to deepen the classmate can study under Executioncontextswitcher, SECURITYCONTEXT.RESTORECURRENTWI, ExecutionContext these several east.

In fact, the details of the physical thread can not be too concerned about, know its "main thread a logic---" Asynchronous task thread B logic, the main thread C logic "the basic principle can be. In addition, Async will also be wired overhead, so you should be reasonable to use the business scenario.

Summarize

From the gradual analysis of async, it is found that the async approach provided by NET is basically same strain, such as:
1. net4.5 's async, throw away the grammatical sugar is the Net4.0 task+ state machine.
2. net4.0 task, degraded to 3.5 is (Thread, ThreadPool) + implementation of the wait, cancel and other API operations.

This article takes the async as the starting point, has analyzed its internal principle and the realization briefly, hoped to be helpful to everybody.

Explore the async, await anatomy of C #

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.