Reprinted: http://www.vchelp.net/ The original author's name fang (fangguicheng@21cn.com) Text asynchronous IO, APC, IO completed port, thread pool and high-performance server four-thread pool ponds under the MSDN " Thread pooling. Threads with many applications spend a lot of time in sleep state to wait for the event. There are also some threads entering the sleep state, periodically being woken up to change or update status information. The thread pool allows you to use thread more effectively, which provides a worker thread pool managed by the system. At least there will be a thread to listen to all waiting operations that are placed in the thread pool. When the wait operation is complete, there will be a worker thread in the thread pool to perform the corresponding callback function. You can also put the work items that don't wait for action into the thread pool, use the QueueUserWorkItem function to complete this work, pass the work item function to be executed to the thread pool through a parameter. After the project is placed in the thread pool, it cannot be canceled. Timer-Queue Timers and Registered Wait Operations are also implemented using thread pools. Their callback function is also placed in the thread pool. You can also use the BindiocompletionCallback function to deliver an asynchronous IO operation. On the IO completion port, the callback function is also performed by the thread pool thread. When the QueueUserWorkItem function or the BindiocompletionCallback function is called, the thread pool is automatically created, or the Timer-Queue Timers or Registered Wait Operations is placed in the callback function, the thread pool can also be created. The number of thread pools can be created is not limited, only limited to available memory, each thread uses the default initial stack size, running on the default priority. There are two types of threads in the thread pool: IO threads and non-IO threads. The IO thread waits in the alarm state, and the work item is placed in the IO thread as the APC. If your work item needs thread execution in a warning state, you should put it in the IO thread. Non-IO worker threads wait on IO to complete ports, using non-IO threads than IO thread efficiency, that is, as long as possible, try to use non-IO threads. IO threads and non-IO threads will not exit before asynchronous IO operations are not completed. However, do not issue asynchronous IO requests that need to be completed in a non-IO thread. The correct use of the thread pool is that the work project function and all functions it will call must be a thread pool. Safe functions should not assume that the thread is a disposable thread or a permanent thread. In general, it should be avoided using thread local storage and issuing asynchronous IO calls that require permanent threads, such as the RegNotifyChangeKeyValue function. If you need to perform such a function in a permanent thread, you can deliver an option WT_ExecuteinPersistribTTHREAD to QueueUserWorkItem. Note that the thread pool cannot be compatible with the Single-threaded case (STA) model of COM. In order to explain more in depth, we must first try to achieve a simple thread pool model.
code show as below:/********************************************** ************************* / / * TESTUROUR w thread pool. * // ************ *********************************************************** ********** / typedef struct _THREAD_POOL {HANDLE QuitEvent; HANDLE WorkItemSemaphore; LONG WorkItemCount; LIST_ENTRY WorkItemHeader; CRITICAL_SECTION WorkItemLock; LONG ThreadNum; HANDLE * ThreadsArray;} THREAD_POOL, * PTHREAD_POOL; typedef VOID (* WORK_ITEM_PROC) ( PVOID Param); typedef struct _WORK_ITEM {LIST_ENTRY List; WORK_ITEM_PROC UserProc; PVOID UserParam;} WORK_ITEM, * PWORK_ITEM; DWORD WINAPI WorkerThread (PVOID pParam) {PTHREAD_POOL pThreadPool = pParam (PTHREAD_POOL); HANDLE Events [2]; Events [0] = pThreadPool-> QuitEvent; Events [1] = pThreadPool-> WorkItemSemaphore; for (;;) {DWORD dwRet = WaitForMultipleObjects (2, Events, FALSE, INFINITE); if (dwRet == WAIT_OBJECT_0) break; // // execu . Te user's proc // else if (dwRet == WAIT_OBJECT_0 1) {PWORK_ITEM pWorkItem; PLIST_ENTRY pList; EnterCriticalSection (& pThreadPool-> WorkItemLock); _ASSERT (! IsListEmpty (& pThreadPool-> WorkItemHeader)); pList = RemoveHeadList (& pThreadPool-> WorkItemHeader); LeaveCriticalSection (& pThreadPool-> WorkItemLock); pWorkItem = CONTAINING_RECORD (pList, WORK_ITEM, List); pWorkItem-> UserProc (pWorkItem-> UserParam); InterlockedDecrement (& pThreadPool-> WorkItemCount); free (pWorkItem);
} Else {_ASSERT (0); break;}} return 0;} BOOL InitializeThreadPool (PTHREAD_POOL pThreadPool, LONG ThreadNum) {pThreadPool-> QuitEvent = CreateEvent (NULL, TRUE, FALSE, NULL); pThreadPool-> WorkItemSemaphore = CreateSemaphore (NULL , 0, 0x7FFFFFFF, NULL); pThreadPool-> WorkItemCount = 0; InitializeListHead (& pThreadPool-> WorkItemHeader); InitializeCriticalSection (& pThreadPool-> WorkItemLock); pThreadPool-> ThreadNum = ThreadNum; pThreadPool-> ThreadsArray = (HANDLE *) malloc (sizeof (Handle); for (int i = 0; i
if (pWorkItem == NULL) return FALSE; pWorkItem-> UserProc = UserProc; pWorkItem-> UserParam = UserParam; EnterCriticalSection (& pThreadPool-> WorkItemLock); InsertTailList (& pThreadPool-> WorkItemHeader, & pWorkItem-> List); LeaveCriticalSection (& pThreadPool-> WorkItemLock); InterlockedIncrement (& pThreadPool-> WorkItemCount); ReleaseSemaphore (pThreadPool-> WorkItemSemaphore, 1, NULL); return TRUE;} vOID UserProc1 (PVOID dwParam) {WorkItem (dwParam);} void TestSimpleThreadPool (BOOL bWaitMode, LONG ThreadNum) { THREAD_POOL ThreadPool; InitializeThreadPool (& ThreadPool, ThreadNum); CompleteEvent = CreateEvent (NULL, FALSE, FALSE, NULL); BeginTime = GetTickCount (); ItemCount = 20; for (int i = 0; i <20; i ) {PostWorkItem (& ThreadPool UserProc1, (pvoid) BWAITMODE);} WaitForsingleObject (CompleteEvent, Infinite); CloseHandle (& ThreadPool);} We put your work items in a queue, use a semaphore notify the thread pool, any thread pool A thread takes out the work item to execute, after execution The thread returns to the thread pool and continues to wait for a new work item. The number of threads in the thread pool is fixed, pre-created, permanent threads until the thread pool is destroyed, and these threads will be destroyed. Thread pools Get the opportunity to get work items are equal, random, and no special way to ensure that which thread has special priority to obtain work items. Moreover, the number of threads that can be run in concurrent at the same time is not limited. In fact, in the demo code of our execution calculation task, all threads are executed concurrently. Below, let's take another look, complete the same task, how the system provides how it works.