Asynchronous, multi-thread, task, and parallel programming: select a suitable multi-thread model
Overview:
@ FCL4.0 the existing thread models and their similarities and differences;
@ Multithreading programming model selection.
1: The nature of Asynchronization, multithreading, task, and Parallelism
These four concepts correspond to the nature of CLR, and are essentially multithreading.
Asynchronous mode: The BeginInvoke and EndInvoke modes, which are managed in the internal thread pool of CLR;
Multithreading is embodied in C # and can be initiated by the type Thread. It can also be initiated by ThreadPool. The former is not managed by the CLR thread pool, and the latter is. For the convenience of various programming models, the FCL team also provided BackgroundWorker and several timers, which are basically enhancement of ThreadPool and added some interaction functions with caller threads;
Task is a new feature of FCL4.0. In a place called the Task parallel Library (TPL), it is actually in the namespace of System. Threading. Tasks. The name of the task parallel library is very mysterious. In fact, it is also the enhancement of the CLR thread pool. Optimized the scheduling algorithm between threads and added the interaction function with the caller thread;
Parallel is a new feature of FCL4.0 and also belongs to TPL. Parallel tasks are used in the background for management. To put it bluntly, because tasks Use thread pool threads, Parallel naturally uses thread pool threads for management. Its essence is simply to further simplify tasks. Here we need to enhance our understanding of parallelism. In fact, multithreading is parallel. In a timely manner, there is no need for a parallel job library. The Thread type is used to create two new threads. the CLR or Windows system will schedule the two threads to be executed on two CPUs as needed. Therefore, it is not because CLR supports parallel computing only when the task parallel library is added. The task parallel Library only provides a set of Apis so that we can better manipulate threads for parallel development.
2: Sorry
Uncle Jeffrey Richter said Microsoft provided such a multi-threaded model, and it was a pity because it created chaos. Many developers do not know which type to use to write their own multi-threaded code. We always love and hate Microsoft. It constantly updates something and forces us to keep learning. However, progress makes it impossible to die too early, so that we can lose our job.
C # just came out with a smile, and now many of its syntax features are more elegant than Java. In many cases, we are so good at ridicule that we can only cry. By the way, I still like JAVA, but I haven't used it for a long time.
3: Now, what to use to write Multithreading
If you write code in FRAMEWORK4.0, you should write multi-threaded code based on this priority:
Priority |
Priority |
Not Allowed |
Parallel (including extension library PLinq) Task |
ThreadPool (BackgroundWorker, Timer) Asynchronous |
Thread |
This table provides priority guidance in most cases, but in some cases there are exceptions.
3.1: Why does Parallel have the same priority as the Task, not better than the Task?
Although Parallel uses tasks for management in the background and simplifies operations on tasks, it has an important feature difference with Task: Parallel blocks caller threads. Check the Paralle members, including the For, ForEach, and Invoke methods. It does not even provide a BeginInvoke method, which also implies this. However, despite the synchronous execution, Parallel still allocates multiple tasks to multiple CPUs.
The Start method is the most commonly used Task. It does not block the main thread. Although the Task also provides the synchronous thread startup method RunSynchronously, it is generally not used much.
3.2: when to use Asynchronization, when to use thread or thread pool
This should start with "Direct Memory Access Mode for I/O operations. Data exchange through DMA can hardly consume CPU resources. In hardware, hard disks, NICS, sound cards, and video cards all have DMA functions. We can simply think that when our worker threads need to operate on I/O resources (such as reading a large file, reading a webpage, and reading a Socke package ), we need to do these tasks asynchronously. The asynchronous mode only occupies the CLR thread pool at the beginning and end of work. In other cases, hardware devices such as hard disks and network adapters are used to handle specific work, this will not overoccupy CPU space and time consumption.
In summary:
Computing-intensive work, directly using threads;
IO-intensive work, adopting asynchronous mechanism;
When we do not know what the job is I/O-intensive, an inappropriate guide is: to view MEMBERS OF THE FCL type, if the member provides a method similar to BeginDosomething, it is preferred to use it, instead of starting a new thread or throwing it into the thread pool.
3.3: Advantages of Thread Pool
New threads bring about great overhead. These overhead are mainly concentrated on the memory space required for allocating the thread kernel objects, thread environment blocks, user mode stacks, and kernel mode stacks, load the DLL's DLLMain method, pass the connection flag, and thread context switch. Because threads are so expensive, the thread pool is a good choice for common development requirements. The thread pool manages worker threads for developers. When a job is finished, CLR will not destroy the thread, but will keep the thread for a period of time to see if other jobs need it. The CLR determines when to destroy or start a new thread.
3.4: when to use Thread
The preceding Thread models are all threads. So when does Thread need to appear directly?
The most important reason for using Thread is that we need to control the priority of the Thread. The Thread model above the Thread does not support priority setting. Setting the high priority of a thread can give it more CPU time;
Furthermore, the thread can be controlled as the foreground thread. Of course, the new Thread is the foreground Thread by default. The front-end Thread is not interrupted with the interruption of the caller Thread, which allows us to use the Thread for some key operations.