當使用CreateProcess呼叫時,系統將建立一個程式和一個主執行緒。CreateThread將在主執行緒的基礎上建立一個新執行緒,大致做如下步驟:
- 在核心物件中分配一個執行緒標識/控制程式碼,可供管理,由CreateThread返回
- 把執行緒退出碼置為STILL_ACTIVE,把執行緒掛起計數置1
- 分配context結構
- 分配兩頁的物理儲存以準備棧,保護頁設定為PAGE_READWRITE,第2頁設為PAGE_GUARD
- lpStartAddr和lpvThread值被放在棧頂,使它們成為傳送給StartOfThread的引數
- 把context結構的棧指標指向棧頂(第5步)指令指標指向startOfThread函式
語法:
1 2 3 4 5 6 7 8 9 10 |
hThread = CreateThread(&security_attributes, dwStackSize, ThreadProc,pParam, dwFlags, &idThread) ; HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes DWORD dwStackSize, // initial thread stack size LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function LPVOID lpParameter, // argument for new thread DWORD dwCreationFlags, // creation flags LPDWORD lpThreadId // pointer to receive thread ID ); |
第一個引數是指向SECURITY_ATTRIBUTES型態的結構的指標。在Windows 98中忽略該引數。在Windows NT中,它被設為NULL。
第二個引數是用於新執行緒的初始堆疊大小,預設值為0。在任何情況下,Windows根據需要動態延長堆疊的大小。
第三個引數是指向執行緒函式的指標。函式名稱沒有限制,但是必須以下列形式宣告:
1 |
DWORD WINAPI ThreadProc (PVOID pParam) ; |
第四個引數為傳遞給ThreadProc的引數。這樣主執行緒和從屬執行緒就可以共享資料。
第五個引數通常為0,但當建立的執行緒不馬上執行時為旗標CREATE_SUSPENDED。執行緒將暫停直到呼叫ResumeThread來恢復執行緒的執行為止。
第六個引數是一個指標,指向接受執行緒ID值的變數。
注意:臨界區要線上程執行前初始化,因為執行緒一但被建立即開始執行(除非手工掛起),但執行緒建立後在初始化臨界區可能出現問題
如:孫鑫MFC中的現象
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int main() { InitializeCriticalSection(&g_cs); //先初始化臨界區 HANDLE handle1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL); HANDLE handle2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL); CloseHandle(handle1); CloseHandle(handle2); Sleep(4000); DeleteCriticalSection(&g_cs); return 0; } |