在Windows的多線程編程中,建立線程的函數主要有CreateThread和_beginthread(及_beginthreadex)。編程
使用API函數CreateThread建立線程時,其中的線程函數原型:安全
HANDLE WINAPI CreateThread( _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ SIZE_T dwStackSize, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD lpThreadId );
當線程函數的起始地址無效(或者不可訪問)時,CreateThread函數仍可能成功返回。若是該起始地址無效,則當線程運行時,異常將發生,線程終止。並返回一個錯誤代碼。 在線程函數返回後,其返回值用做調用ExitThread函數的參數(由系統隱式調用)。可使用GetExitCodeThread函數得到該線程函數的返回值。服務器
使用CreateThread建立的線程具備THREAD_PRIORITY_NORMAL的線程優先級。可使用GetThreadPriority和SetThreadPriority函數獲取和設置線程優先級值。
系統中的線程對象一直存活到線程結束,而且全部指向它的句柄都經過調用CloseHandle關閉後。多線程
對於使用C運行時庫裏的函數的線程應該使用_beginthread和_endthread這些C運行時函數來管理線程,而不是使用CreateThread和ExitThread。不然,當調用ExitThread後,可能引起內存泄露。函數
uintptr_t _beginthread( // NATIVE CODE void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist ); uintptr_t _beginthread( // MANAGED CODE void( __clrcall *start_address )( void * ), unsigned stack_size, void *arglist ); uintptr_t _beginthreadex( // NATIVE CODE void *security, unsigned stack_size, unsigned ( __stdcall *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr ); uintptr_t _beginthreadex( // MANAGED CODE void *security, unsigned stack_size, unsigned ( __clrcall *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr );
在使用_beginthread或者_beginthreadex建立線程時,應該包含頭文件<process.h>,而且須要設置多線程版 本的運行時庫。「Project Settings」--> 「C/C++」-->「Category」-->「Code Generation」-->「Use Run-Time Library」-->「Multithreaded」和「Debug Multithreaded」。這至關於給編譯添加了一個編譯選項/MT,使編譯器在編譯時在.obj文件中使用libcmt.lib文件名而不是 libc.lib。鏈接器使用這個名字與運行時庫函數鏈接。
能夠調用_endthread和_endthreadex顯示式結束一個線程。然而,當線程函數返回時,_endthread和_endthreadex 被自動調用。endthread和_endthreadex的調用有助於確保分配給線程的資源的合理回收。_endthread自動地關閉線程句柄,然而 _endthreadex卻不會。所以,當使用_beginthread和_endthread時,不須要顯示調用API函數CloseHandle式關 閉線程句柄。該行爲有別於API函數ExitThread的調用。_endthread和_endthreadex回收分配的線程資源後,調用 ExitThread。
當_beginthread和_beginthreadex被調用時,操做系統本身處理線程棧的分配。若是在調用這些函數時,指定棧大小爲0,則操做系統 爲該線程建立和主線程大小同樣的棧。若是任何一個線程調用了abort、exit或者ExitProcess,則全部線程都將被終止。ui
CreateThread、_beginthread和_beginthreadex都是用來啓動線程的,_beginthread是_beginthreadex的功能子集,雖然_beginthread內部是調用_beginthreadex但他屏蔽了象安全特性這樣的功能,因此_beginthread與CreateThread不是同等級別,_beginthreadex和CreateThread在功能上徹底可替代,這兩個函數一個是運行時庫函數(C Run-Time Library Reference),一個是WIN32 的庫函數(Process and Thread Reference),CRT(C Run-Time)包含了像malloc(), fopen(), _open(), strtok(), ctime(), 或localtime()等函數須要專門的線程局部存儲的數據塊,這個數據塊一般須要在建立線程的時候就創建,若是使用CreateThread,這個數據塊就沒有創建,而後會怎樣呢?在這樣的線程中仍是可使用這些函數並且沒有出錯,實際上函數發現這個數據塊的指針爲空時,會本身創建一個,而後將其與線程聯繫在一塊兒,這意味着若是你用CreateThread來建立線程,而後使用這樣的函數,會有一塊內存在不知不覺中建立,遺憾的是,這些函數並不將其刪除,而CreateThread和ExitThread也沒法知道這件事,因而就會有Memory Leak,在線程頻繁啓動的軟件中(好比某些服務器軟件),早晚會讓系統的內存資源耗盡!操作系統