詳解_beginthreadex()創(chuàng)建線程
一、使用_beginthreadex()
需要的頭文件支持#include // for _beginthread()
需要的設(shè)置:ProjectàSetting-->C/C++-->User run-time library
選擇Debug Multithreaded
或者Multithreaded
。即使用: MT
或MTD
。
代碼如下:
#include <stdio.h> #include <string> ? ? ? ? ? ? // for STL string class #include <windows.h> ? ? ? ? ?// for HANDLE #include <process.h> ? ? ? ? ?// for _beginthread() using namespace std; class ThreadX { private: ? int loopStart; ? int loopEnd; ? int dispFrequency; public: ? string threadName; ? ThreadX( int startValue, int endValue, int frequency ) ? { ?? ?loopStart = startValue; ?? ?loopEnd = endValue; ?? ?dispFrequency = frequency; ? } ? static unsigned __stdcall ThreadStaticEntryPoint(void * pThis) ? { ?? ? ?ThreadX * pthX = (ThreadX*)pThis; ? // the tricky cast ?? ? ?pthX->ThreadEntryPoint(); ? ? ? ? ? // now call the true entry-point-function ?? ? ?return 1;?? ??? ??? ??? ??? ??? ? ? ? ?// the thread exit code ? } ? void ThreadEntryPoint() ? { ?? ?for (int i = loopStart; i <= loopEnd; ++i) ?? ?{ ?? ? ?if (i % dispFrequency == 0) ?? ? ?{ ?? ??? ? ?printf( "%s: i = %d\n", threadName.c_str(), i ); ?? ? ?} ?? ?} ?? ?printf( "%s thread terminating\n", threadName.c_str() ); ? } }; int main() { ? ? ThreadX * o1 = new ThreadX( 0, 1, 2000 ); ? ? HANDLE ? hth1; ? ? unsigned ?uiThread1ID; ? ? hth1 = (HANDLE)_beginthreadex( NULL, ? ? ? ? // security ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, ? ? ? ? ? ?// stack size ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ThreadX::ThreadStaticEntryPoint, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?o1, ? ? ? ? ? // arg list ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?CREATE_SUSPENDED, ?// so we can later call ResumeThread() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&uiThread1ID ); ? ? if ( hth1 == 0 ) ? ? ? ? printf("Failed to create thread 1\n"); ? ? DWORD ? dwExitCode; ? ? GetExitCodeThread( hth1, &dwExitCode ); ?// should be STILL_ACTIVE = 0x00000103 = 259 ? ? printf( "initial thread 1 exit code = %u\n", dwExitCode ); ? ? o1->threadName = "t1"; ? ? ThreadX * o2 = new ThreadX( -100000, 0, 2000 ); ? ? HANDLE ? hth2; ? ? unsigned ?uiThread2ID; ? ? hth2 = (HANDLE)_beginthreadex( NULL, ? ? ? ? // security ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, ? ? ? ? ? ?// stack size ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ThreadX::ThreadStaticEntryPoint, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?o2, ? ? ? ? ? // arg list ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?CREATE_SUSPENDED, ?// so we can later call ResumeThread() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&uiThread2ID ); ? ? if ( hth2 == 0 ) ? ? ? ? printf("Failed to create thread 2\n"); ? ? GetExitCodeThread( hth2, &dwExitCode ); ?// should be STILL_ACTIVE = 0x00000103 = 259 ? ? printf( "initial thread 2 exit code = %u\n", dwExitCode ); ? ? o2->threadName = "t2"; ? ? ResumeThread( hth1 ); ? // serves the purpose of Jaeschke's t1->Start() ? ? ResumeThread( hth2 ); ?? ? ? WaitForSingleObject( hth1, INFINITE ); ? ? WaitForSingleObject( hth2, INFINITE ); ? ? GetExitCodeThread( hth1, &dwExitCode ); ? ? printf( "thread 1 exited with code %u\n", dwExitCode ); ? ? GetExitCodeThread( hth2, &dwExitCode ); ? ? printf( "thread 2 exited with code %u\n", dwExitCode ); ? ? CloseHandle( hth1 ); ? ? CloseHandle( hth2 ); ? ? delete o1; ? ? o1 = NULL; ? ? delete o2; ? ? o2 = NULL; ? ? printf("Primary thread terminating.\n"); ?? ?return 0; }
注意:
- (1)如果你正在編寫C/C++代碼,決不應(yīng)該調(diào)用
CreateThread
。相反,應(yīng)該使用VisualC++運(yùn)行期庫函數(shù)_beginthreadex
,退出也應(yīng)該使用_endthreadex
。如果不使用Microsoft
的VisualC++編譯器,你的編譯器供應(yīng)商有它自己的CreateThread
替代函數(shù)。不管這個(gè)替代函數(shù)是什么,你都必須使用。 - (2)因?yàn)?code>_beginthreadex和
_endthreadex
是CRT線程函數(shù),所以必須注意編譯選項(xiàng)runtimelibaray
的選擇,使用MT或MTD。[MultiThreaded , Debug MultiThreaded]
。 - (3
)_beginthreadex
函數(shù)的參數(shù)列表與CreateThread
函數(shù)的參數(shù)列表是相同的,但是參數(shù)名和類型并不完全相同。這是因?yàn)镸icrosoft的C/C++運(yùn)行期庫的開發(fā)小組認(rèn)為,C/C++運(yùn)行期函數(shù)不應(yīng)該對Windows數(shù)據(jù)類型有任何依賴。_beginthreadex
函數(shù)也像CreateThread
那樣,返回新創(chuàng)建的線程的句柄。 - (4)C++主線程的終止,同時(shí)也會終止所有主線程創(chuàng)建的子線程,不管子線程有沒有執(zhí)行完畢。所以上面的代碼中如果不調(diào)用
WaitForSingleObject
,則2個(gè)子線程t1和t2可能并沒有執(zhí)行完畢或根本沒有執(zhí)行。 - (5)如果某線程掛起,然后有調(diào)用
WaitForSingleObject
等待該線程,就會導(dǎo)致死鎖。所以上面的代碼如果不調(diào)用resumethread
,則會死鎖。
二、_beginthreadex()與代CreateThread()區(qū)別
CreateThread
是Windows的API函數(shù)(SDK函數(shù)的標(biāo)準(zhǔn)形式,直截了當(dāng)?shù)膭?chuàng)建方式,任何場合都可以使用),提供操作系統(tǒng)級別的創(chuàng)建線程的操作,且僅限于工作者線程。不調(diào)用MFC和RTL的函數(shù)時(shí),可以用CreateThread
,其它情況不要輕易。在使用的過程中要考慮到進(jìn)程的同步與互斥的關(guān)系(防止死鎖)。線程函數(shù)定義為:DWORD WINAPI _yourThreadFun(LPVOID pParameter
)。但它沒有考慮:
- (1)
C Runtime
中需要對多線程進(jìn)行紀(jì)錄和初始化,以保證C函數(shù)庫工作正常(典型的例子是strtok函數(shù))。 - (2)
MFC
也需要知道新線程的創(chuàng)建,也需要做一些初始化工作(當(dāng)然,如果沒用MFC就沒事了)。
AfxBeginThread:MFC中線程創(chuàng)建的MFC函數(shù),首先創(chuàng)建了相應(yīng)的CWinThread對象,然后調(diào)用CWinThread::CreateThread, 在CWinThread::CreateThread中,完成了對線程對象的初始化工作,然后,調(diào)用_beginthreadex(AfxBeginThread相比較更為安全)創(chuàng)建線程。它簡化了操作或讓線程能夠響應(yīng)消息,即可用于界面線程,也可以用于工作者線程,但要注意不要在一個(gè)MFC程序中使用_beginthreadex()或CreateThread()。線程函數(shù)定義為:UINT
_yourThreadFun(LPVOID pParam)
_beginthreadex:MS對C Runtime庫的擴(kuò)展SDK函數(shù),首先針對C Runtime庫做了一些初始化的工作,以保證C Runtime庫工作正常。然后,調(diào)用CreateThread真正創(chuàng)建線程。 僅使用Runtime Library時(shí),可以用_BegingThread。
- 小節(jié):實(shí)際上,這三個(gè)函數(shù)之間存在一定的調(diào)用關(guān)系,第一個(gè)純粹一些,后兩個(gè)完成自己相應(yīng)的工作之后,調(diào)用前者實(shí)現(xiàn)線程的創(chuàng)建。其中
CreateThread
是由操作系統(tǒng)提供的接口,而AfxBeginThread
和_BeginThread
則是編譯器對它的封裝。 - 小節(jié):用_
beginthreadex()
、_endthreadex
函數(shù)應(yīng)該是最佳選擇,且都是C Run-time Library中的函數(shù),函數(shù)的參數(shù)和數(shù)據(jù)類型都是C Run-time Library
中的類型,這樣在啟動線程時(shí)就不需要進(jìn)行Windows數(shù)據(jù)類型和C Run-time Library
中的數(shù)據(jù)類型之間的轉(zhuǎn)化,從而,減低了線程啟動時(shí)的資源消耗和時(shí)間的消耗。但使用_beginthread
,無法創(chuàng)建帶有安全屬性的新線程,無法創(chuàng)建暫停的線程,也無法獲得 線程ID,_endthread
的情況類似,它不帶參數(shù),這意味這線程的退出代碼必須硬編碼為0。 - 小節(jié):MFC也是C++類庫(只不過是Microsoft的C++類庫,不是標(biāo)準(zhǔn)的C++類庫),在MFC中也封裝了new和delete兩中運(yùn)算符,所以用到new和delete的地方不一定非要使用_beginthreadex() 函數(shù),用其他兩個(gè)函數(shù)都可以。
_beginthreadex
和_beginthread
在回調(diào)入口函數(shù)之前進(jìn)行一些線程相關(guān)的CRT的初始化操作。
CRT的函數(shù)庫在線程出現(xiàn)之前就已經(jīng)存在,所以原有的CRT不能真正支持線程,
這也導(dǎo)致了許多CRT的函數(shù)在多線程的情況下必須有特殊的支持,不能簡單的使用CreateThread就OK。
補(bǔ)充一點(diǎn):_beginthreadex()是針對CRT的線程函數(shù),在線程中若要用到CRT的函數(shù),最好用這個(gè)啟動線程,如果不用這個(gè)會有內(nèi)存泄漏。
到此這篇關(guān)于詳解_beginthreadex()
創(chuàng)建線程的文章就介紹到這了,更多相關(guān)_beginthreadex()創(chuàng)建線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
與ASCII碼相關(guān)的C語言字符串操作函數(shù)
這篇文章主要介紹了與ASCII碼相關(guān)的C語言字符串操作函數(shù),分別是將字符轉(zhuǎn)換為ASCII碼的toascii()函數(shù)和根據(jù)ASCII碼進(jìn)行字符串比較的strcoll()函數(shù),需要的朋友可以參考下2015-08-08OpenCV + MFC實(shí)現(xiàn)簡單人臉識別
這篇文章主要為大家詳細(xì)介紹了OpenCV + MFC實(shí)現(xiàn)簡單人臉識別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08C語言實(shí)現(xiàn)將double/float 轉(zhuǎn)為字符串(帶自定義精度)
這篇文章主要介紹了C語言實(shí)現(xiàn)將double/float 轉(zhuǎn)為字符串(帶自定義精度),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12C++實(shí)現(xiàn)快速排序(Quicksort)算法
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)快速排序(Quicksort)算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04Qt添加MSVC2017編譯器的實(shí)現(xiàn)方法
Qt添加MSVC2017編譯器是開發(fā)者在Windows平臺上進(jìn)行Qt應(yīng)用程序開發(fā)的重要步驟,本文詳細(xì)介紹了如何為Qt配置MSVC2017編譯器的具體步驟,感興趣的可以了解一下2023-09-09