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庫的選擇:

 

    對於線程的支持是后來的事!這也導致了許多CRT的函數在多線程的情況下必須有特殊的支持,不能簡單的使用CreateThread就OK。大多的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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM