Before TPL (task parallel Library) is available, threadpool is used to process multi-threaded transactions and waits, which may be similar to the following:Code:
1 Class Program 2 { 3 [Threadstatic] 4 Static Int Perthreadvalue; 5 6 Static Void Main (String [] ARGs) 7 { 8 Console. writeline ( " Main thread: {0} " , 9 Thread. currentthread. managedthreadid ); 10 11 Console. writeline (); 12 13 For ( Int I = 1 ; I <= 5 ; I ++ ) 14 { 15 Autoresetevent signalouter = New Autoresetevent ( False ); 16 Threadpool. queueuserworkitem (S) => 17 { 18 Perthreadvalue = I; 19 Console. writeline ( " Launch thread: {0}, value: {1} " , 20 Thread. currentthread. managedthreadid, perthreadvalue ); 21 22 Autoresetevent signalinner = New Autoresetevent ( False ); 23 Threadpool. queueuserworkitem (n) => 24 { 25 Console. writeline ( " Nested thread: {0}, value: {1} " , 26 Thread. currentthread. managedthreadid, perthreadvalue ); 27 Signalinner. Set (); 28 }); 29 Signalinner. waitone (); 30 31 Console. writeline ( " Launch back thread: {0}, value: {1} " , 32 Thread. currentthread. managedthreadid, perthreadvalue ); 33 Signalouter. Set (); 34 }); 35 Signalouter. waitone (); 36 } 37 38 Console. readkey (); 39 } 40 }
Threadpool willProgramThe domain maintains a FIFO first-in-first-out queue. When queueuserworkitem is called, the thread pool puts the specified task into the queue and takes the task out of the queue for execution when there is another available thread.
Therefore, the execution solution finds that each task is executed on different threads.
When. NET Framework 4 provides the TPL library, we can use another method to accomplish the same task.
1 Class Program 2 { 3 [Threadstatic] 4 Static Int Perthreadvalue; 5 6 Static Void Main ( String [] ARGs) 7 { 8 Console. writeline ( " Main thread: {0} " , 9 Thread. currentthread. managedthreadid ); 10 11 Console. writeline (); 12 13 For ( Int I =1 ; I <= 5 ; I ++ ) 14 { 15 Task. Factory. startnew ( 16 () => 17 { 18 Perthreadvalue = I; 19 Console. writeline ( " Launch thread: {0}, value: {1} " , 20 Thread. currentthread. managedthreadid, perthreadvalue ); 21 22 Task. Factory. startnew ( 23 () => 24 { 25 Console. writeline ( " Nested thread: {0}, value: {1} " , 26 Thread. currentthread. managedthreadid, perthreadvalue ); 27 }). Wait (); 28 29 Console. writeline ( " Launch back thread: {0}, value: {1} " , 30 Thread. currentthread. managedthreadid, perthreadvalue ); 31 }). Wait (); 32 } 33 34 Console. readkey (); 35 } 36 }
Generally, we can see that nested tasks use the same thread pool thread as external calls and waiting tasks.
If the machine is fast enough, basically all tasks are executed on the same thread.
In TPL, taskscheduler is used to schedule task execution. taskscheding has a feature named "task inlining ".
When the external threadpool thread is blocking and waiting for the completion of nested nestedtasks, nestedtask may be executed on the waiting thread.
The advantage of this is that it can improve the performance, because it saves both the use of blocked threads.
Possible problems during use:
If threadstatic is used to mark a variable, the variable is stored independently for each thread TLS, and the variable is always shared in the same thread.
However, in the example shown, if the value of the variable is specified in the parent task and the execution thread, and the sub-task and the same execution thread use the same variable value, A problem may occur under a certain requirement.