In depth analysis of C asynchronous programming details

  • 2020-05-10 18:45:42
  • OfStack

The difference between synchronous and asynchronous methods
The synchronized method call needs to wait for the synchronized method to finish executing and return the result before the program can continue
Asynchronous methods are returned immediately after being called so that the program can perform other operations while the called method completes its tasks
Overview of asynchronous programming
.NET Framework allows you to invoke any method asynchronously. Define a delegate that has the same signature as the method you need to call; The common language runtime will automatically have the appropriate signature for the delegate definition
The BeginInvoke and EndInvoke methods.
The BeginInvoke method is used to start the asynchronous call. It has the same parameters as the method you need to execute asynchronously, except for two additional parameters (described later).
BeginInvoke returns immediately, without waiting for the asynchronous call to complete.
BeginInvoke returns IasyncResult, which can be used to monitor the progress of the call.
The EndInvoke method is used to retrieve the results of the asynchronous call. The EndInvoke method can be called at any time after BeginInvoke is called. If the asynchronous call does not complete, EndInvoke blocks 1 straight up to
The asynchronous call completes. The parameters for EndInvoke include the out and ref parameters for the method you want to execute asynchronously (as in Visual Basic) < Out > ByRef and ByRef) and by
BeginInvoke returns IAsyncResult.
Four common methods for making asynchronous calls using BeginInvoke and EndInvoke. After calling BeginInvoke, you can:
1. Do something, then call EndInvoke 1 and block until the call is complete.
2. Get WaitHandle using IAsyncResult.AsyncWaitHandle, use its WaitOne method to perform 1 straight block to emit the WaitHandle signal, and then call
EndInvoke. This is where the main program waits for the asynchronous method and waits for the result of the asynchronous method.
3. Poll IAsyncResult returned by BeginInvoke, IAsyncResult.IsCompeted to determine when the asynchronous call is completed, and then call EndInvoke. This process is personally thought to be related to
The same.
4. Pass the delegate for the callback method to BeginInvoke. This method is executed on the ThreadPool thread after the asynchronous call is completed, and it can call EndInvoke. This is mandatory
Replace the callback function with IAsyncResult.AsyncState (the last parameter of BeginInvoke method) as the delegate, and then use the delegate to execute EndInvoke.
Warning     always calls EndInvoke after the asynchronous call completes.
If you don't understand the above, you can understand it later.
 
example
1) let's start with a simple example of an asynchronous method without a callback function
Please read the comments carefully when you run the program. It is helpful to understand. Also, if you synchronize both of the commented methods, you will find the speed advantage of running asynchronously.

using System;
 namespace ConsoleApplication1
 {
     class Class1
     {
         // Commissioned by the statement 
         public delegate void AsyncEventHandler();

         // Asynchronous methods 
         void Event1()
        {
            Console.WriteLine("Event1 Start");
            System.Threading.Thread.Sleep(4000);
            Console.WriteLine("Event1 End");
        }
        //  Synchronized methods 
        void Event2()
        {
            Console.WriteLine("Event2 Start");
            int i=1;
            while(i<1000)
            {
                i=i+1;
                Console.WriteLine("Event2 "+i.ToString());
            }
            Console.WriteLine("Event2 End");
        }
        [STAThread]
        static void Main(string[] args)
        {
            long start=0;
            long end=0;
            Class1 c = new Class1();
            Console.WriteLine("ready");
            start=DateTime.Now.Ticks;
            // Commissioned by instance 
            AsyncEventHandler asy = new AsyncEventHandler(c.Event1);
            // The asynchronous call starts with no callback functions and AsyncState, for null
            IAsyncResult ia = asy.BeginInvoke(null, null);
            // Synchronizing starts, 
            c.Event2();
            // End asynchronously. If no end occurs, 1 Block until the call is complete, and return the function's return , if any. 

            asy.EndInvoke(ia);
            // It's all synchronous. 
            //c.Event1();
            //c.Event2();

            end =DateTime.Now.Ticks;
            Console.WriteLine(" Time scale difference ="+ Convert.ToString(end-start) );
            Console.ReadLine();
        }
    }
}

2) let's look at the asynchronous operation of WebRequest and WebResponse with callback functions.

using System;
using System.Net;
using System.Threading;
using System.Text;
using System.IO;
// RequestState  Class is used to pass 
//  Asynchronous calls pass data 
public class RequestState
{
    const int BUFFER_SIZE = 1024;
    public StringBuilder RequestData;
    public byte[] BufferRead;
    public HttpWebRequest Request;
    public Stream ResponseStream;
    //  Create a decoder of the appropriate encoding type 
    public Decoder StreamDecode = Encoding.UTF8.GetDecoder();
    public RequestState()
    {
        BufferRead = new byte[BUFFER_SIZE];
        RequestData = new StringBuilder("");
        Request = null;
        ResponseStream = null;
    }
}
// ClientGetAsync  Make an asynchronous request 
class ClientGetAsync
{
    public static ManualResetEvent allDone = new ManualResetEvent(false);
    const int BUFFER_SIZE = 1024;
    public static void Main(string[] args)
    {
        if (args.Length < 1)
        {
            showusage();
            return;
        }
        //  Get it from the command line  URI
        Uri HttpSite = new Uri(args[0]);
        //  Create the request object 
        HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(HttpSite);
        //  Creating a state object 
        RequestState rs = new RequestState();
        //  Add the request to the state so that it can be passed back and forth 
        rs.Request = wreq;
        //  Make an asynchronous request 
        IAsyncResult r = (IAsyncResult)wreq.BeginGetResponse(new AsyncCallback(RespCallback), rs);
        //  will  ManualResetEvent  Set to  Wait . 
        //  So that the application does not exit before calling the callback 
        allDone.WaitOne();
    }
    public static void showusage()
    {
        Console.WriteLine(" Try to get  (GET) 1 a  URL");
        Console.WriteLine("\r\n Usage: :");
        Console.WriteLine("ClientGetAsync URL");
        Console.WriteLine(" Example: :");
        Console.WriteLine("ClientGetAsync http://www.microsoft.com/net/");
    }
    private static void RespCallback(IAsyncResult ar)
    {
        //  Get from asynchronous results  RequestState  object 
        RequestState rs = (RequestState)ar.AsyncState;
        //  from  RequestState  To obtain  HttpWebRequest
        HttpWebRequest req = rs.Request;
        //  call  EndGetResponse  generate  HttpWebResponse  object 
        //  This object comes from the request made above 
        HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(ar);
        //  Now that we have the response, we should follow 
        //  The response stream is starting to read 
        Stream ResponseStream = resp.GetResponseStream();
        //  This read operation is also done asynchronously, so we 
        //  Will be in  RequestState  Storage flow 
        rs.ResponseStream = ResponseStream;
        //  Please note that, rs.BufferRead  Is passed to the  BeginRead . 
        //  This is where the data will be read in. 
        IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
    }
    private static void ReadCallBack(IAsyncResult asyncResult)
    {
        //  from  asyncresult  To obtain  RequestState  object 
        RequestState rs = (RequestState)asyncResult.AsyncState;
        //  Take out the  RespCallback  Set in the  ResponseStream
        Stream responseStream = rs.ResponseStream;
        //  At this time  rs.BufferRead  Should have 1 Some of the data. 
        //  The read operation will tell us if there is data there 
        int read = responseStream.EndRead(asyncResult);
        if (read > 0)
        {
            //  To prepare  Char  Array buffer, used to send  Unicode  conversion 
            Char[] charBuffer = new Char[BUFFER_SIZE];
            //  Converts the byte stream to  Char  Array, and then convert to a string 
            // len  Shows how many characters are converted to  Unicode
            int len = rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBuffer, 0);
            String str = new String(charBuffer, 0, len);
            //  Appends the most recently read data to  RequestData stringbuilder  Object, 
            //  The object is contained in  RequestState  In the 
            rs.RequestData.Append(str);
            //  Now send another 1 Three asynchronous calls to read more data 
            //  Note that this procedure will be called again and again until 
            // responseStream.EndRead  return  -1
            IAsyncResult ar = responseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
        }
        else
        {
            if (rs.RequestData.Length > 1)
            {
                //  All data has been read, so it is displayed to the console 
                string strContent;
                strContent = rs.RequestData.ToString();
                Console.WriteLine(strContent);
            }
            //  Close the response flow 
            responseStream.Close();
            //  Set up the  ManualResetEvent So that the main thread can exit 
            allDone.Set();
        }
        return;
    }
}

There are callback functions and asynchronous operations in asynchronous callbacks.
First, get ResponseStream asynchronously, and then read the data asynchronously.
This is a classic program. You can learn a lot from it. Let's talk about it together.
conclusion
As mentioned above,.net framework can invoke any method asynchronously. So asynchrony is very useful.
There are also many methods for asynchronous invocation in the.net framework class library. Generally, 1 is the macro representation of asynchronous operation with the beginning of Begin and the end of End forming 1 pair, asynchronous delegate method, plus two callback functions and AsyncState parameters. So to do asynchronous programming, don't forget to delegate delegate, Begin, End, AsyncCallBack delegate, AsyncState instance (cast by IAsyncResult.AsyncState in the callback function), IAsycResult(monitor async), that's enough to understand what async is all about.

Related articles: