Resolve the C instances of synchronous and asynchronous calls to of delegates

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

The Invoke method of the delegate is used to make synchronous calls. Synchronous calls can also be called block calls, which block the current thread, execute the call, and continue down after the call is complete.
Examples of synchronous calls:

using System;
using System.Threading;
public delegate int AddHandler(int a, int b);
public class Foo {
 static void Main() {
  Console.WriteLine("**********SyncInvokeTest**************");
  AddHandler handler = new AddHandler(Add);
  int result = handler.Invoke(1,2);
  Console.WriteLine("Do other work... ... ...");
  Console.WriteLine(result);
  Console.ReadLine();
 }

 static int Add(int a, int b) {
  Console.WriteLine("Computing "+a+" + "+b+" ...");
  Thread.Sleep(3000);
  Console.WriteLine("Computing Complete.");
  return a+b;
 }
} Operation results: 
**********SyncInvokeTest**************
Computing 1 + 2 ...
Computing Complete.
Do other work... ... ...

Synchronous calls block threads, and if you're calling a heavy task (such as a large number of IO operations), it can make the program stop for a long time, which can be bad
The user experience, where asynchronous invocation is necessary.
Instead of blocking the thread, the asynchronous call plugs the call into the thread pool, and the program's main thread or UI thread can continue executing.
The asynchronous invocation of the delegate is implemented through BeginInvoke and EndInvoke.
Asynchronous call:

using System;
using System.Threading;
public delegate int AddHandler(int a, int b);
public class Foo {
 static void Main() {
  Console.WriteLine("**********AsyncInvokeTest**************");
  AddHandler handler = new AddHandler(Add);
  IAsyncResult result = handler.BeginInvoke(1,2,null,null);
  Console.WriteLine("Do other work... ... ...");
  Console.WriteLine(handler.EndInvoke(result));
  Console.ReadLine();
 }

 static int Add(int a, int b) {
  Console.WriteLine("Computing "+a+" + "+b+" ...");
  Thread.Sleep(3000);
  Console.WriteLine("Computing Complete.");
  return a+b;
 }
} Operation results:  **********AsyncInvokeTest**************
Do other work... ... ...
Computing 1 + 2 ...
Computing Complete.

As you can see, the main thread doesn't wait, but runs straight down.
However, the problem remains that when the main thread reaches EndInvoke, if the call does not end (which is likely), the thread will still be blocked while waiting for the result of the call.
The solution is to use callback functions, which are automatically called when the call ends
Callback asynchronous:

public class Foo {
 static void Main() {
  Console.WriteLine("**********AsyncInvokeTest**************");
  AddHandler handler = new AddHandler(Add);
  IAsyncResult result = handler.BeginInvoke(1,2,new AsyncCallback(AddComplete),"AsycState:OK");
  Console.WriteLine("Do other work... ... ...");
  Console.ReadLine();
 }

 static int Add(int a, int b) {
  Console.WriteLine("Computing "+a+" + "+b+" ...");
  Thread.Sleep(3000);
  Console.WriteLine("Computing Complete.");
  return a+b;
 }

 static void AddComplete(IAsyncResult result) {
  AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;
  Console.WriteLine(handler.EndInvoke(result));
  Console.WriteLine(result.AsyncState);
 }
}


Related articles: