1. 程式人生 > >Windows執行緒的建立和終止

Windows執行緒的建立和終止

執行緒的建立

CreateThread, AfxBeginThread,_beginthread, _beginthreadex的區別 

    CreateThread是Windows的API函式,提供作業系統級別的建立執行緒的操作,且僅限於工作者執行緒。不呼叫MFC和RTL的函式時,可以用CreateThread,其它情況不要輕易。在使用的過程中要考慮到程序的同步與互斥的關係(防止死鎖)。執行緒函式定義為:DWORD WINAPI ThreadFun(PVOID pParameter)。MSDN:http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx 

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

    _beginthreadex:MS的C/C++執行期庫函式,是對C Runtime庫的擴充套件SDK函式,首先針對C Runtime庫做了一些初始化的工作,以保證C Runtime庫工作正常。然後,呼叫CreateThread真正建立執行緒。MSDN:http://msdn.microsoft.com/en-us/library/kdzttdcb(v=vs.80).aspx

摘自《windows核心程式設計》:   
    CreateThread函式是用來建立執行緒的Windows函式。不過,如果你正在編寫C/C++程式碼,決不應該呼叫CreateThread。相反,應該使用Visual C++執行期庫函式_beginthreadex。如果不使用Microsoft的Visual C++編譯器,你的編譯器供應商有它自己的CreateThred替代函式。   
    若要使多執行緒C和C++程式能夠正確地執行,必須建立一個數據結構,並將它與使用C/C++執行期庫函式的每個執行緒關聯起來。當你呼叫C/C++執行期庫時,這些函式必須知道檢視呼叫執行緒的資料塊,這樣就不會對別的執行緒產生不良影響。  
    1.每個執行緒均獲得由C/C++執行期庫的堆疊分配的自己的tiddata記憶體結構(tiddata結構位於Mtdll.h檔案中)。
    2.傳遞給_beginthreadex的執行緒函式的地址儲存在tiddata記憶體塊中。傳遞給該函式的引數也儲存在該資料塊中。   
    3._beginthreadex確實從內部呼叫CreateThread,因為這是作業系統瞭解如何建立新執行緒的唯一方法。   
    4.當呼叫CreatetThread時,它被告知通過呼叫_threadstartex而不是pfnStartAddr(執行緒函式地址)來啟動執行新執行緒。還有,傳遞給執行緒函式的引數是tiddata結構而不是pvParam的地址。    

    5.如果一切順利,就會像CreateThread那樣返回執行緒控制代碼。如果任何操作失敗了,便返回NULL。   

    beginthreadex和_beginthread函式的區別:_beginthread函式的引數比較少,因此位元性全面的_beginthreadex函式受到更大的限制。例如,如果使用_beginthread,就無法建立帶有安全屬性的新執行緒,無法建立暫停的執行緒,也無法獲得執行緒的ID值。


    CRT的函式庫線上程出現之前就已經存在,所以原有的CRT不能真正支援執行緒,這導致我們在程式設計的時候有了CRT庫的選擇,C/C++執行期庫: 

 
    對於執行緒的支援是後來的事!這也導致了許多CRT的函式在多執行緒的情況下必須有特殊的支援,不能簡單的使用CreateThread就行。大多的CRT函式都可以在CreateThread執行緒中使用,但並不是所有的都沒有問題! 

    有些CRT的函式象malloc(),fopen(),_open(),strtok(),ctime(),或localtime()等函式需要專門的執行緒區域性儲存的資料塊,這個資料塊通常需要在建立執行緒的時候就建立,如果使用CreateThread,這個資料塊就沒有建立,然後會怎樣呢?在這樣的執行緒中還是可以使用這些函式而且沒有出錯,實際上函式發現這個資料塊的指標為空時,會自己建立一個,然後將其與執行緒聯絡在一起,這意味著如果你用CreateThread來建立執行緒,然後使用這樣的函式,會有一塊記憶體在不知不覺中建立,遺憾的是,這些函式並不將其刪除,而CreateThread和ExitThread也無法知道這件事,於是就會有資源洩漏的問題,線上程頻繁啟動的軟體中(比如某些伺服器軟體),遲早會讓系統的記憶體資源耗盡! 

    _beginthreadex(內部也呼叫CreateThread)和_endthreadex就對這個記憶體塊做了處理,所以沒有問題!(不會有人故意用CreateThread建立然後用_endthreadex終止吧,而且執行緒的終止最好不要顯式的呼叫終止函式,自然退出最好!) 


執行緒的終止


《windows核心程式設計》:若要終止執行緒的執行,可以使用下面的方法:
1.執行緒函式返回(最好使用這種方法)。
2.通過呼叫ExitThread函式,執行緒將自行撤消(最好不要使用這種方法)。
3.同一個程序或另一個程序中的執行緒呼叫TerminateThread函式(應該避免使用這種方法)。
4.包含執行緒的程序終止執行(應該避免使用這種方法)。

下面是MSDN對這幾種終止執行緒執行方法的說明:

1)BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);
http://msdn.microsoft.com/en-us/library/ms686717(v=VS.85).aspx

2)VOID ExitThread(DWORD dwExitCode);
http://msdn.microsoft.com/en-us/library/ms682659(v=VS.85).aspx

3)void _endthread(void);
  void _endthreadex(unsigned retval);
http://msdn.microsoft.com/en-us/library/hw264s73(VS.80).aspx

4)Terminating a Thread
http://msdn.microsoft.com/en-us/library/ms686724(v=VS.85).aspx