HANDLE WINAPI CreateThread ( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTRIBUTES 的指針,為新線程指定安全描述 __in SIZE_T dwStackSize, // 初始化線程堆棧尺寸 __in LPTHREAD_START_ROUTINE lpStartAddress, //線程函數所指向的地址起始函數 __in_opt LPVOID lpParameter, // 給線程函數傳遞的參數 __in DWORD dwCreationFlags, // 有關線程的標志 __out_opt LPDWORD lpThreadId //系統分配給線程的ID );
----第一個參數是安全屬性,一般設為null,使用缺省的安全屬性。當我們想此線程有另外的子進程時,可改變它的屬性。
----第二個參數是線程堆棧尺寸,一般設為0,表示與此應用的堆棧尺寸相同,即主線程與創建的線程一樣長度的堆棧。並且其長度會根據需要自動變長。
----第三個參數,也是最重要的一個,是一個指向函數名的指針,或者函數名字
----第四個參數是你需要向線程函數傳遞的參數,一般是一個指向結構的指針。不需傳遞參數時,則這個參數設為null。
----第五個參數,傳入與線程有關的一些標志,如果是CREATE_SUSPENDED,則創建一個掛起的線程,即這個線程本身已創建,它的堆棧也已創建。但這個線程不會被分配給CPU時間,只有當ResumeThread函數被調用后才能執行;當然,也可以調用SuspendThread函數再次掛起線程。要是標志為0,那么一旦建立線程,線程函數就被立即調用。一般傳為0即可。 ----第六個參數是系統分配給這個線程的唯一的ID標志
// MultiTread2.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include <windows.h> #include <stdio.h> #define MAX_THREADS 10 typedef struct MyData { int val1; int val2; //char key[32]; }MYDATA; DWORD WINAPI ThreadProc(LPVOID lpParam) { MYDATA *pmd = (MYDATA *)lpParam; printf("%d\n", pmd->val1); printf("%d\n", pmd->val2); return 0; } DWORD(WINAPI *pThreadProc)(LPVOID lpParam); void fun() { pThreadProc = ThreadProc; MYDATA mydt[MAX_THREADS]; HANDLE hThread[MAX_THREADS]; int i; for (i = 0; i < MAX_THREADS; i++) { mydt[i].val1 = i; mydt[i].val2 = i + 1; hThread[i] = CreateThread( NULL,// default security attributes 0,// use default stack size pThreadProc,// thread function &mydt[i],// argument to thread function 0, // use default creation flags NULL); if (hThread[i] == NULL) { ExitProcess(i); } } // Wait until all threads have terminated. WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); //這樣傳給回調函數的參數不用定位static或者new出來的了 // Close all thread handles upon completion. for (i = 0; i < MAX_THREADS; i++) { CloseHandle(hThread[i]); } } int _tmain(int argc, _TCHAR* argv[]) { fun(); getchar(); return 0; }
注意:傳給函數的參數,要保證當運行回調函數時候,參數不能被銷毀。
比如這里參數是局部變量棧。
如果將
WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); //這樣傳給回調函數的參數不用定位static或者new出來的了
屏蔽,
那么傳遞給回調函數的參數就可能已經被銷毀,調用函數的時候就會出錯、
除非將傳入的參數定義為static 或者其他在調用完所有線程前不被銷毀的變量
WaitForSingleObject的返回值能夠指明調用線程為什么再次變為可調度狀態。如果線程等待的對象變為已通知狀態,那么返回值是 WAIT_OBJECT_0。如果設置的超時已經到期,則返回值是WAIT_TIMEOUT。如果將一個錯誤的值(如一個無效句柄)傳遞給 WaitForSingleObject,那么返回值將是WAIT_FAILED(若要了解詳細信息,可調用GetLastError)。
DWORD WaitForMultipleObjects( DWORD dwCount, CONST HANDLE* phObjects, BOOL fWaitAll, DWORD dwMilliseconds );
說明這一情況的一些示例代碼: HANDLE h[3]; h[0] = hProcess1; h[1] = hProcess2; h[2] = hProcess3; DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); switch(dw) { case WAIT_FAILED: // Bad call to function (invalid handle?) break; case WAIT_TIMEOUT: // None of the objects became signaled within 5000 milliseconds. break; case WAIT_OBJECT_0 + 0: // The process identified by h[0] (hProcess1) terminated. break; case WAIT_OBJECT_0 + 1: // The process identified by h[1] (hProcess2) terminated. break; case WAIT_OBJECT_0 + 2: // The process identified by h[2] (hProcess3) terminated. break; }
如果為fWaitAll參數傳遞 FALSE,WaitForMultipleObjects就從索引0開始向上對句柄數組進行掃描,同時已通知的第一個對象終止等待狀態。
這可能產生一些 你不希望有的結果。
例如,通過將3個進程句柄傳遞給該函數,你的線程就會等待3個子進程終止運行。如果數組中索引為0的進程終止運 行,WaitForMultipleObjects就會返回。這時該線程就可以做它需要的任何事情,然后循環反復,等待另一個進程終止運行。
如果該線程傳 遞相同的3個句柄,該函數立即再次返回WAIT_OBJECT_0。除非刪除已經收到通知的句柄,否則代碼就無法正確地運行