網站首頁 編程語言 正文
一、使用_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 ? 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++代碼,決不應該調用
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
,則會死鎖。
二、_beginthreadex()與代CreateThread()區別 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
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的函數,最好用這個啟動線程,如果不用這個會有內存泄漏。
原文鏈接:https://www.xuebuyuan.com/3255482.html
相關推薦
- 2022-07-13 實現基于 session+redis 的防重復提交
- 2024-01-16 linux查看外網ip的5種方法
- 2022-11-13 Redis中HyperLogLog的使用詳情_Redis
- 2022-07-18 spring boot 中解決 Invalid character found in the req
- 2022-05-23 一起來學習C++的函數指針和函數對象_C 語言
- 2023-09-18 document.getElementById()獲取一直為null
- 2022-05-06 pycharm使用sftp同步服務器的步驟_python
- 2022-08-22 C++動態規劃實現查找最長公共子序列_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支