您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何用_beginthreadex()創建線程”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何用_beginthreadex()創建線程”吧!
需要的頭文件支持#include // for _beginthread()
需要的設置: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 hth2; unsigned uiThread1ID; hth2 = (HANDLE)_beginthreadex( NULL, // security 0, // stack size ThreadX::ThreadStaticEntryPoint, o1, // arg list CREATE_SUSPENDED, // so we can later call ResumeThread() &uiThread1ID ); if ( hth2 == 0 ) printf("Failed to create thread 1\n"); DWORD dwExitCode; GetExitCodeThread( hth2, &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 hth3; unsigned uiThread2ID; hth3 = (HANDLE)_beginthreadex( NULL, // security 0, // stack size ThreadX::ThreadStaticEntryPoint, o2, // arg list CREATE_SUSPENDED, // so we can later call ResumeThread() &uiThread2ID ); if ( hth3 == 0 ) printf("Failed to create thread 2\n"); GetExitCodeThread( hth3, &dwExitCode ); // should be STILL_ACTIVE = 0x00000103 = 259 printf( "initial thread 2 exit code = %u\n", dwExitCode ); o2->threadName = "t2"; ResumeThread( hth2 ); // serves the purpose of Jaeschke's t1->Start() ResumeThread( hth3 ); WaitForSingleObject( hth2, INFINITE ); WaitForSingleObject( hth3, INFINITE ); GetExitCodeThread( hth2, &dwExitCode ); printf( "thread 1 exited with code %u\n", dwExitCode ); GetExitCodeThread( hth3, &dwExitCode ); printf( "thread 2 exited with code %u\n", dwExitCode ); CloseHandle( hth2 ); CloseHandle( hth3 ); delete o1; o1 = NULL; delete o2; o2 = NULL; printf("Primary thread terminating.\n"); return 0; }
注意:
(1)如果你正在編寫C/C++代碼,決不應該調用CreateThread
。相反,應該使用VisualC++運行期庫函數_beginthreadex
,退出也應該使用_endthreadex
。如果不使用Microsoft
的VisualC++編譯器,你的編譯器供應商有它自己的CreateThread
替代函數。不管這個替代函數是什么,你都必須使用。
(2)因為_beginthreadex
和_endthreadex
是CRT線程函數,所以必須注意編譯選項runtimelibaray
的選擇,使用MT或MTD。[MultiThreaded , Debug MultiThreaded]
。
(3)_beginthreadex
函數的參數列表與CreateThread
函數的參數列表是相同的,但是參數名和類型并不完全相同。這是因為Microsoft的C/C++運行期庫的開發小組認為,C/C++運行期函數不應該對Windows數據類型有任何依賴。_beginthreadex
函數也像CreateThread
那樣,返回新創建的線程的句柄。
(4)C++主線程的終止,同時也會終止所有主線程創建的子線程,不管子線程有沒有執行完畢。所以上面的代碼中如果不調用WaitForSingleObject
,則2個子線程t1和t2可能并沒有執行完畢或根本沒有執行。
(5)如果某線程掛起,然后有調用WaitForSingleObject
等待該線程,就會導致死鎖。所以上面的代碼如果不調用resumethread
,則會死鎖。
CreateThread
是Windows的API函數(SDK函數的標準形式,直截了當的創建方式,任何場合都可以使用),提供操作系統級別的創建線程的操作,且僅限于工作者線程。不調用MFC和RTL的函數時,可以用CreateThread
,其它情況不要輕易。在使用的過程中要考慮到進程的同步與互斥的關系(防止死鎖)。線程函數定義為:DWORD WINAPI _yourThreadFun(LPVOID pParameter
)。但它沒有考慮:
(1)C Runtime
中需要對多線程進行紀錄和初始化,以保證C函數庫工作正常(典型的例子是strtok函數)。
(2)MFC
也需要知道新線程的創建,也需要做一些初始化工作(當然,如果沒用MFC就沒事了)。
AfxBeginThread:MFC中線程創建的MFC函數,首先創建了相應的CWinThread對象,然后調用CWinThread::CreateThread, 在CWinThread::CreateThread中,完成了對線程對象的初始化工作,然后,調用_beginthreadex(AfxBeginThread相比較更為安全)創建線程。它簡化了操作或讓線程能夠響應消息,即可用于界面線程,也可以用于工作者線程,但要注意不要在一個MFC程序中使用_beginthreadex()或CreateThread()。線程函數定義為:UINT
_yourThreadFun(LPVOID pParam)
_beginthreadex:MS對C Runtime庫的擴展SDK函數,首先針對C Runtime庫做了一些初始化的工作,以保證C Runtime庫工作正常。然后,調用CreateThread真正創建線程。 僅使用Runtime Library時,可以用_BegingThread。
小節:實際上,這三個函數之間存在一定的調用關系,第一個純粹一些,后兩個完成自己相應的工作之后,調用前者實現線程的創建。其中CreateThread
是由操作系統提供的接口,而AfxBeginThread
和_BeginThread
則是編譯器對它的封裝。
小節:用_beginthreadex()
、_endthreadex
函數應該是最佳選擇,且都是C Run-time Library中的函數,函數的參數和數據類型都是C Run-time Library
中的類型,這樣在啟動線程時就不需要進行Windows數據類型和C Run-time Library
中的數據類型之間的轉化,從而,減低了線程啟動時的資源消耗和時間的消耗。但使用_beginthread
,無法創建帶有安全屬性的新線程,無法創建暫停的線程,也無法獲得 線程ID,_endthread
的情況類似,它不帶參數,這意味這線程的退出代碼必須硬編碼為0。
小節:MFC也是C++類庫(只不過是Microsoft的C++類庫,不是標準的C++類庫),在MFC中也封裝了new和delete兩中運算符,所以用到new和delete的地方不一定非要使用_beginthreadex() 函數,用其他兩個函數都可以。
_beginthreadex
和_beginthread
在回調入口函數之前進行一些線程相關的CRT的初始化操作。
CRT的函數庫在線程出現之前就已經存在,所以原有的CRT不能真正支持線程,
這也導致了許多CRT的函數在多線程的情況下必須有特殊的支持,不能簡單的使用CreateThread就OK。
補充一點:_beginthreadex()是針對CRT的線程函數,在線程中若要用到CRT的函數,最好用這個啟動線程,如果不用這個會有內存泄漏。
感謝各位的閱讀,以上就是“如何用_beginthreadex()創建線程”的內容了,經過本文的學習后,相信大家對如何用_beginthreadex()創建線程這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。