C # Asynchronous delegate

Source: Internet
Author: User
Tags mscorlib

In C #, a delegate type is a type-safe, object-oriented function pointer. When we define a delegate type through the delegate keyword, the compiler generates three methods for the delegate type: Invoke, BeginInvoke, and EndInvoke.

For example, for the following delegate type, you can view the three methods generated by the compiler through Ilspy.

Private Delegate int Numberadd (intint b);

Executing a delegate instance synchronously

In an application that uses delegates, the most common is to execute the delegate instance synchronously by using the Invoke () method. That is, the thread that invokes the delegate waits until the delegate call is complete.

Here is an example of a synchronous execution of a delegate that simulates a time-consuming operation through sleep (3000) in a Numberadd delegate instance:

Numberadd Numberadd = (A, b) = ={Thread.Sleep ( the); Console.WriteLine ("----> Numberadd () on thread is {0}", Thread.CurrentThread.ManagedThreadId); Console.WriteLine ("----> start to Calc {0} + {1}", A, b); Console.WriteLine ("----> Test result is {0}", A +b); returnA +b;}; Console.WriteLine ("main thread (ID: {0}) invoke Numberadd function", Thread.CurrentThread.ManagedThreadId);//int result = Numberadd (2, 5);intresult = Numberadd.invoke (2,5); Console.WriteLine ("main thread (ID: {0}) Get the result: {1}", Thread.CurrentThread.ManagedThreadId, result);

The output of the code is below, as can be seen from the results, the main thread executes the delegate instance process will be blocked until the delegate instance execution completes, the main thread will continue to execute.

In many applications, a method may take a long time, such as loading a large document, or performing a time-consuming database operation. If we execute the method synchronously, the main thread will block until the execution of the method is done, and the performance is that the application has no corresponding impact on the user experience. At this point, you can consider the invocation of the method through the asynchronous nature of the delegate.

BeginInvoke () and EndInvoke ()

Before beginning the introduction of asynchronous execution of a delegate, first look at the BeginInvoke () and EndInvoke () methods, combined with the above delegate type Numberadd, to analyze the parameters and return types of the two methods.

. Method  Public HidebysigNewSlotVirtual     instance class[Mscorlib]system.iasyncresult BeginInvoke (Int32A,Int32B,class[Mscorlib]system.asynccallback Callback,Object 'Object') Runtimemanaged {} //end of Method Numberadd::begininvoke
    The
    • BeginInvoke () method is used to start an asynchronous call that has the same parameters as the delegate type, and two optional parameters for the Int32 A and int32 b
    • BeginInvoke () methods in this example:
      • Asyn The Ccallback delegate, which allows you to specify the method (callback function)
      • user-defined object to invoke when the asynchronous call completes, which can pass information to the callback method
    • BeginInvoke () Returns immediately after the method call, without waiting for the delegate to complete, that is, the calling thread is not blocked, and you can continue execution of
    • BeginInvoke () returns an object that implements the IAsyncResult interface, which can be used to monitor the progress of an asynchronous call When you are ready to get the result of a method call, you can pass it to the EndInvoke () method
. Method  Public Hidebysig Virtual     instance Int32 EndInvoke (        class  [mscorlib]system.iasyncresult result    managed  //  End of method Numberadd::endinvoke
    • The EndInvoke method return type is the return type of the delegate type, in this case int32
    • EndInvoke only one parameter that implements the IAsyncResult interface (the return result of the BeginInvoke () method), combined with this parameter, the EndInvoke () method can get the result of an asynchronous call
    • After calling the BeginInvoke () method, you can call the EndInvoke () method at any time, and if the asynchronous call has not yet completed, the EndInvoke () method will block the calling thread until the asynchronous call is complete before allowing the calling thread to execute
Executing a delegate instance asynchronously

After introducing the BeginInvoke () and EndInvoke () methods, look at an example of an asynchronous invocation method.

Console.WriteLine ("main thread (ID: {0}) invoke Numberadd function", Thread.CurrentThread.ManagedThreadId); IAsyncResult IAsyncResult= Numberadd.begininvoke (2,5,NULL,NULL); Console.WriteLine ("main thread (ID: {0}) can do something after BeginInvoke", Thread.CurrentThread.ManagedThreadId); for(inti =0; I <5; i++) Console.WriteLine ("......"); Console.WriteLine ("main thread (ID: {0}) wait at EndInvoke", Thread.CurrentThread.ManagedThreadId);
The main thread will block at the EndInvoke call until the asynchronous call execution is completeintresult =Numberadd.endinvoke (IAsyncResult); Console.WriteLine ("main thread Get the result: {0}", result);

The output of the code is that you can see that the asynchronous delegate actually uses a new thread to execute the Numberadd instance so that the main thread does not block after BeginInvoke and can continue execution, but when the main thread executes to EndInvoke, Because the asynchronous call has not yet completed, the main thread will block at EndInvoke.

In fact, this example still has a big problem, the main thread will still be blocked. Here's a little bit of improvement to see the asynchronous call state by polling.

Polling for asynchronous call states

In the IAsyncResult interface, by implementing the IsCompleted property of an instance of this interface, you can detect an indication that the asynchronous operation is complete, or false if the operation completes.

Simply look at the members of IAsyncResult:

    • AsyncState: Gets a user-defined object that can be used as a parameter of a callback function to pass information from the calling thread to the callback function
    • AsyncWaitHandle: Gets the WaitHandle used to wait for the asynchronous operation to complete
    • completedsynchronously: Gets a value that indicates whether the asynchronous operation is complete synchronously
    • IsCompleted: Gets a Boolean value that indicates whether the asynchronous operation has completed

So, the code can take advantage of iscompleted to get the state of an asynchronous operation:

Console.WriteLine ("main invoke Numberadd function"); IAsyncResult IAsyncResult= Numberadd.begininvoke (2,5,NULL,NULL); while(iasyncresult.iscompleted! =true) {Console.WriteLine ("main thread can do something after BeginInvoke"); Console.WriteLine ("......"); Thread.Sleep ( -);}intresult =Numberadd.endinvoke (IAsyncResult); Console.WriteLine ("main thread Get the result: {0}", result);

Similarly, there is a AsyncWaitHandle attribute in the IAsyncResult type instance, which allows for more flexible wait logic.

This property returns an instance of the WaitHandle type, through which the WaitOne method of the instance can invoke synchronization between the thread and the Async method:

Console.WriteLine ("main invoke Numberadd function"); IAsyncResult IAsyncResult= Numberadd.begininvoke (2,5,NULL,NULL); while(!iasyncresult.asyncwaithandle.waitone ( -) {Console.WriteLine ("main thread can do something after BeginInvoke"); Console.WriteLine ("......");}intresult =Numberadd.endinvoke (IAsyncResult); Console.WriteLine ("main thread Get the result: {0}", result);
Using AsyncCallback

It is also not a good way to detect the execution state of an asynchronous calling method by polling, and the best way to implement the invocation of an asynchronous method is to specify the callback function by AsyncCallback the delegate. This allows the asynchronous thread to proactively notify the calling thread when the asynchronous method completes.

A callback function, numberaddcompleted, is provided in the following example, and the callback function is called when the asynchronous method execution completes.

Note : You need to get a delegate instance in the callback function before you can call the EndInvoke method to get the result of the Async method execution, so the example uses "System.Runtime.Remoting.Messaging" The asyncresult type in the namespace to get the instance of the delegate.

Console.WriteLine ("main invoke Numberadd function"); IAsyncResult IAsyncResult= Numberadd.begininvoke (2,5, numberaddcompleted,"This was a msg from main"); for(inti =0; I <5; i++) {Console.WriteLine ("main thread can do something after BeginInvoke"); Console.WriteLine ("......"); Thread.Sleep ( -);}Private Static voidnumberaddcompleted (IAsyncResult IAsyncResult) {Console.WriteLine ("numberadd function complete, run callback function"); AsyncResult AsyncResult=(AsyncResult) IAsyncResult; Console.WriteLine (Asyncresult.asyncstate as string); Get a delegate instance by AsyncResult type instance Numberadd numberadd=(Numberadd) asyncresult.asyncdelegate; intresult =Numberadd.endinvoke (IAsyncResult); Console.WriteLine ("main thread Get the result: {0}", result); }
Summarize

This article describes the BeginInvoke () and EndInvoke () methods that the C # compiler generates for delegate types. A simple example demonstrates how to use the BeginInvoke () and EndInvoke () methods to complete the asynchronous invocation of a method.

You can consider using asynchronous delegates when we need to perform time-consuming operations and do not want the calling thread to be blocked. The example of delegate asynchronous execution shows that the underlying use of the asynchronous delegate is multithreaded (directly using threads in the thread pool). So, where we use asynchronous delegates, we can do it in a multi-threaded way.

C # Asynchronous delegate

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.