1. 程式人生 > >windows系統中建立執行緒常用的函式及其區別

windows系統中建立執行緒常用的函式及其區別

在windows系統中建立執行緒的函式有以下幾個方法:

CreadThread,AfxBeginThread,_beginthread,_beginthreadex。

一、CreateThread

HANDLE WINAPI CreateThread(
  __in          LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in          SIZE_T dwStackSize,
  __in          LPTHREAD_START_ROUTINE lpStartAddress,
  __in          LPVOID lpParameter,
  __in          DWORD dwCreationFlags,
  __out         LPDWORD lpThreadId
);

CreateThread是Windows的API函式(SDK函式的標準形式,直截了當的建立方式,任何場合都可以使用),提供作業系統級別的建立執行緒的操作,且僅限於工作者執行緒。不呼叫MFC和RTL的函式時,可以用CreateThread,其它情況不要輕易。在使用的過程中要考慮到程序的同步與互斥的關係(防止死鎖)。
執行緒函式定義為:DWORD WINAPI _yourThreadFun(LPVOID pParameter)。但它沒有考慮:
1、C Runtime中需要對多執行緒進行紀錄和初始化,以保證C函式庫工作正常(典型的例子是strtok函式)。
2、MFC也需要知道新執行緒的建立,也需要做一些初始化工作(當然,如果沒用MFC就沒事了)。

二、__beginthread

uintptr_t _beginthread(
       void( *start_address )( void * ),
       unsigned stack_size,
       void *arglist
    );

三、_beginthreadex

uintptr_t _beginthreadex(
       void *security,
       unsigned stack_size,
       unsigned ( *start_address )( void * ),
       void *arglist,
       unsigned initflag,
       unsigned *thrdaddr
    );

_beginthreadex:MS對C Runtime庫的擴充套件SDK函式,首先針對C Runtime庫做了一些初始化的工作,以保證C Runtime庫工作正常。然後,呼叫CreateThread真正建立執行緒。 僅使用Runtime
Library時,可以用_BegingThread。

四、

CWinThread* AfxBeginThread(	 
					AFX_THREADPROC pfnThreadProc,		
				   LPVOID pParam,						  
				    int nPriority = THREAD_PRIORITY_NORMAL,						   
				    UINT nStackSize = 0,						   
				    DWORD dwCreateFlags = 0,						  
				     LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
				     );

AfxBeginThread:MFC中執行緒建立的MFC函式,首先建立了相應的CWinThread物件,然後呼叫CWinThread::CreateThread, 在CWinThread::CreateThread中,完成了對執行緒物件的初始化工作,然後,呼叫_beginthreadex(AfxBeginThread相比較更為安全)建立執行緒。它簡化了操作或讓執行緒能夠響應訊息,即可用於介面執行緒,也可以用於工作者執行緒,但要注意不要在一個MFC程式中使用_beginthreadex()或CreateThread()。執行緒函式定義為:UINT _yourThreadFun(LPVOID pParam)

總結:
1:CreateThread是由作業系統提供的介面,而AfxBeginThread和_BeginThread則是編譯器對它的封裝。
2:用_beginthreadex()、_endthreadex函式應該是最佳選擇,且都是C Run-time Library中的函式,函式的引數和資料型別都是C Run-time Library中的型別,這樣在啟動執行緒時就不需要進行Windows資料型別和C Run-time Library中的資料型別之間的轉化,從而減低了執行緒啟動時的資源消耗和時間的消耗。
3:MFC也是C++類庫(只不過是Microsoft的C++類庫,不是標準的C++類庫),在MFC中也封裝了new和delete兩中運算子,所以用到new和delete的地方不一定非要使用_beginthreadex() 函式,用其他兩個函式都可以。
4:_beginthreadex和_beginthread在回撥入口函式之前進行一些執行緒相關的CRT的初始化操作。CRT的函式庫線上程出現之前就已經存在,所以原有的CRT不能真正支援執行緒,這也導致了許多CRT的函式在多執行緒的情況下必須有特殊的支援,不能簡單的使CreateThread就可以。
5:如果要作多執行緒(非MFC)程式,在主執行緒以外的任何執行緒內
使用malloc(),free(),new呼叫stdio.h或io.h,包括fopen(),open(),getchar(),write(),printf(),errno使用浮點變數和浮點運算函式呼叫那些使用靜態緩衝區的函式如: asctime(),strtok(),rand()等。
應該使用多執行緒的CRT並配合_beginthreadex(該函式只存在於多執行緒CRT), 其他情況,你可以使用單執行緒的CRT並配合CreateThread。因為對產生的執行緒而言,_beginthreadex比CreateThread會為上述操作多做額外的工作,比如幫助strtok()為每個執行緒準備一份緩衝區。
然而多執行緒程式極少情況不使用上述那些函式(比如記憶體分配或者io),所以與其每次都要思考是要使用_beginthreadex還是CreateThread,不如就一棍子敲定_beginthreadex。
6:你也許會藉助win32來處理記憶體分配和io,這時候你確實可以以單執行緒crt配合CreateThread,因為io的重任已經從crt轉交給了win32。這時通常你應該使用HeapAlloc,HeapFree來處理記憶體分配,用CreateFile或者GetStdHandle來處理io。
7:還有一點比較重要的是_beginthreadex傳回的雖然是個unsigned long,其實是個執行緒Handle(事實上_beginthreadex在內部就是呼叫了CreateThread),所以你應該用CloseHandle來結束他。千萬不要使用ExitThread()來退出_beginthreadex建立的執行緒,那樣會喪失釋放簿記資料的機會,應該使用_endthreadex.

下面對兩個概念進行闡述
CRT(C/C++ Runtime Library):
是一種函式庫,由編譯器的生產廠家提供標頭檔案或介面,作業系統提供執行時庫的實現。所以Windows和Linux系統的執行時庫函式介面雖然一樣,但具體實現不一樣。
CRT是支援C/C++執行的一系列函式和程式碼的總稱,雖然沒有一個很精確的定義,但是可以知道,你的main函式就是它負責呼叫的,還有平時使用的strlen,strtok,time,atoi之類的函式也是它提供的。