Detailed explanation of the difference between C multithreading and asynchronous

  • 2021-12-19 06:33:37
  • OfStack

C # Difference between multithreading and asynchronous

With the popularity of CPU (Hyper-Threading, Dual-Core) with multiple hard threads, concurrent programming methods such as multithreading and asynchronous operation have been paid more attention and discussed. This article is mainly to discuss with you master 1 under how to use and send to maximize the performance of the program.

Similarities and differences between multithreading and asynchronous operation

Both multithreading and asynchronous operation can avoid the blocking of the calling thread, thus improving the responsiveness of the software. Sometimes we even think that multithreading and asynchronous operation are equivalent concepts. However, there are some differences between multithreaded and asynchronous operations. These differences result in the difference between the timing of using multithreaded and asynchronous operations.

The essence of asynchronous operation

All programs will eventually be executed by computer hardware, so in order to better understand the nature of asynchronous operation, it is necessary for us to understand its hardware foundation. Friends who are familiar with computer hardware are definitely familiar with the word DMA. The technical specifications of hard disks and optical drives all have clear mode indicators of DMA. In fact, network cards, sound cards and graphics cards also have DMA functions. DMA means direct memory access, that is to say, hardware with DMA function can exchange data with memory without consuming CPU resources. As long as CPU sends an instruction when initiating data transmission, the hardware starts to exchange data with the memory itself, and after the transmission is completed, the hardware will trigger an interrupt to inform the completion of the operation. These I/O operations, which do not consume CPU time, are the hardware basis for asynchronous operations. So asynchronous DMA operations can be initiated even in a single-process (and wireless-thread concept) system such as DOS.

The Essence of Threads

Thread is not a function of computer hardware, but a logical function provided by the operating system. Thread is essentially a piece of code running concurrently in the process, so thread needs the operating system to invest CPU resources to run and schedule.

Advantages and disadvantages of asynchronous operation

Because asynchronous operation does not need extra thread burden and uses callback to process, under the condition of good design, the processing function can not use shared variables (even if it cannot be completely used, at least the number of shared variables can be reduced), which reduces the possibility of deadlock. Of course, asynchronous operation is not perfect. The complexity of writing asynchronous operation is high, and the program mainly uses callback to deal with it, which is new to ordinary people's thinking mode and difficult to debug.

Advantages and disadvantages of multithreading

The advantages of multithreading are obvious. The processing programs in threads are still executed in sequence, which is in line with the thinking habits of ordinary people, so programming is simple. However, the disadvantages of multithreading are also obvious, and the use (abuse) of threads will bring extra burden of context switching to the system. And shared variables between threads may cause deadlocks.

Scope of application

After understanding the advantages and disadvantages of threaded and asynchronous operations, we can explore the reasonable use of threaded and asynchronous operations. In my opinion, when you need to perform I/O operations, using asynchronous operations is more appropriate than using threaded and synchronous I/O operations. I/O operations include not only direct file and network reading and writing, but also cross-process calls such as database operation, Web Service, HttpRequest and. Net Remoting.

The scope of application of threads is the kind of occasions that require long CPU operations, such as time-consuming graphics processing and algorithm execution. However, because of the simplicity and habit of programming with threads, many friends often use threads to perform I/O operations that take a long time. This is harmless when there are only a few concurrent operations, and is not suitable if you need to deal with a large number of concurrent operations.

Case study

Having said that in theory, some brothers may have been impatient for a long time. Now let's study several practical asynchronous operation examples.

Example 1: What happened to the asynchronous method generated by delegate?

As you probably know, using delegate allows a method to be "automatically" invoked asynchronously. Intuitively, I think the compiler or CLR uses another thread to execute the target method. Is this the case or not? Let's prove 1 with 1 piece of code.


using System;
using System.Threading;
 
namespace AsyncDelegateDemo
{
 delegate void AsyncFoo(int i);
 class Program
 {
  ///<summary>
  ///  Output the information of the current thread 
  ///</summary>
  ///<param name="name"> Method name </param>
 
  static void PrintCurrThreadInfo(string name)
  {
   Console.WriteLine("Thread Id of " + name + " is: " + Thread.CurrentThread.ManagedThreadId + ", current thread is "
            + (Thread.CurrentThread.IsThreadPoolThread ? "" : "not ")
            + "thread pool thread.");
  }
 
  ///<summary>
  ///  Test method, Sleep1 Fixed time 
  ///</summary>
  ///<param name="i">Sleep Time of </param>
  static void Foo(int i)
  {
   PrintCurrThreadInfo("Foo()");
   Thread.Sleep(i);
  }
 
  ///<summary>
  ///  Delivery 1 Asynchronous calls 
  ///</summary>
  static void PostAsync()
  {
   AsyncFoo caller = new AsyncFoo(Foo);
   caller.BeginInvoke(1000, new AsyncCallback(FooCallBack), caller);
  }
 
  static void Main(string[] args)
  {
   PrintCurrThreadInfo("Main()");
   for(int i = 0; i < 10 ; i++)
   {
    PostAsync();
   }
   Console.ReadLine();
  }
 
  static void FooCallBack(IAsyncResult ar)
  {
   PrintCurrThreadInfo("FooCallBack()");
   AsyncFoo caller = (AsyncFoo) ar.AsyncState;
   caller.EndInvoke(ar);
  }
 }
}

The output of this code is as follows:


Thread Id of Main() is: 1, current thread is not thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 4, current thread is thread pool thread.
Thread Id of Foo() is: 5, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of FooCallBack() is: 4, current thread is thread pool thread.
Thread Id of Foo() is: 4, current thread is thread pool thread.
Thread Id of Foo() is: 6, current thread is thread pool thread.
Thread Id of FooCallBack() is: 5, current thread is thread pool thread.
Thread Id of Foo() is: 5, current thread is thread pool thread.
Thread Id of Foo() is: 7, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of FooCallBack() is: 4, current thread is thread pool thread.
Thread Id of FooCallBack() is: 6, current thread is thread pool thread.
Thread Id of FooCallBack() is: 5, current thread is thread pool thread.
Thread Id of FooCallBack() is: 7, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.

As you can see from the output, the asynchronous invocation. net uses delegate to "automatically" generate using additional threads (and thread pool threads).

Thank you for reading, hope to help everyone, thank you for your support to this site!


Related articles: