_beginthreadex()和_endthreadex()

本文介绍了C++中线程管理的两个关键函数:_beginthreadex()用于启动线程,并可指定线程的安全属性、堆栈大小及执行函数等;_endthreadex()用于结束线程并返回状态代码。通过示例展示了如何使用这些函数来创建和终止线程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

_beginthreadex()和_endthreadex() - [程序语言]

2008-01-08

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://golog.blogbus.com/logs/10964622.html

线程开始和停止函数! 

unsigned long _beginthreadex( void *security, unsigned stack_size, 
unsigned ( __stdcall *start_address )( void * ),
 void *arglist, unsigned initflag, unsigned *thrdaddr );
第一个参数是线程的安全属性,如果为NULL则为默认安全属性
第二个参数是用来指定线程堆栈的大小,如果为0,则线程堆栈大小和
创建他的线程的相同。一般用0
第三个参数指定线程函数,也就是线程调用执行的函数地址
第四个参数为传递给线程的参数列表 如果多于一个的话,使用结构,然
然后传给结构的指针
最后一个是线程的标识ID
void _endthreadex(unsigned status);
停止线程返回status中指定的代码
例子:
struct agrclist{
  char *data;
  int count;
};

unsigned __stdcall DoTest(void *mArgclist){

  agrclist *pagrclist;
  pagrclist=(struct agrclist *)mArgclist;
  cout << pagrclist->data;
  cout << pagrclist->count;
  _endthreadex(0);
  return 0;
}
void main(void){
 char buf[128];
 HANDLE hThread;
 unsigned int threadid;
 agrclist magrclist,*pmagrclist;
 pmagrclist=&magrclist;
 pmagrclist->data=buf;
 pmagrclist->count=1;
 hThread=(HANDLE)_beginthreadex(NULL,0,&DoTest,pmagrclist,NULL,&threadid);
 closeHandle(hThread);

}


收藏到: Del.icio.us
<think>好的,我现在需要帮助用户解决关于_beginthreadex函数在C++中的使用问题。用户可能想了解如何正确使用这个函数创建线程,或者遇到了相关的编程问题。首先,我应该回忆一下这个函数的基本用法参数。 根据引用[3],_beginthreadex的参数包括安全属性、堆栈大小、线程函数、参数、初始状态线程ID指针。返回值是线程句柄,失败返回0。要注意的是,用户提到C++代码中不应该直接调用CreateThread,而应使用_beginthreadex,如引用[2]所述。这是因为C运行库需要管理线程相关的资源,比如errno变量,而_beginthreadex会正确初始化这些资源,而CreateThread可能不会。 接下来,我需要解释每个参数的作用。安全属性一般设为NULL使用默认,堆栈大小设为0表示默认。线程函数必须使用__stdcall调用约定,返回unsigned类型,并接受void*参数。参数传递多个值时可以用结构体。初始状态0表示立即执行,CREATE_SUSPENDED则挂起。线程ID通过指针返回。 然后,我应该提供一个代码示例,展示如何定义线程函数,调用_beginthreadex,并正确关闭句柄。注意线程结束后要调用CloseHandle,否则会导致资源泄漏。同时,线程函数应该返回一个unsigned值,使用_endthreadex退出,但实际代码中可能直接return。 还要注意错误处理,检查返回值是否为0,处理错误情况。另外,引用[1]提到不同创建线程方法的区别,这里可以强调使用_beginthreadex的优势,比如与C运行库的兼容性。 用户可能遇到的问题包括参数传递错误、线程函数签名不正确、未关闭句柄导致泄漏,或者忘记调用_endthreadex。需要提醒这些注意事项,并解释正确做法。 最后,生成相关问题,帮助用户深入理解,比如参数传递方法、资源释放、与CreateThread的区别等。</think>### _beginthreadex函数用法详解 #### 一、函数原型与参数说明 ```cpp unsigned long _beginthreadex( void* security, // 安全属性(通常置NULL) unsigned stack_size, // 堆栈大小(0表示默认) unsigned (__stdcall* start_address)(void*), // 线程函数地址 void* arglist, // 线程参数(支持结构体传参) unsigned initflag, // 初始状态(0=立即执行,CREATE_SUSPENDED=挂起) unsigned* thrdaddr // 接收线程ID ); ``` **返回值**:成功返回线程句柄(需手动关闭),失败返回0[^3] #### 二、使用步骤 1. **定义线程函数** 需满足`unsigned __stdcall`调用约定: ```cpp unsigned __stdcall ThreadProc(void* pParam) { // 业务逻辑 _endthreadex(0); // 推荐显式调用 return 0; } ``` 2. **创建线程实例** ```cpp HANDLE hThread; unsigned threadID; hThread = (HANDLE)_beginthreadex( NULL, 0, &ThreadProc, (void*)123, // 传递参数 0, &threadID ); if (hThread == 0) { // 错误处理 } ``` 3. **资源释放** ```cpp WaitForSingleObject(hThread, INFINITE); // 等待线程结束 CloseHandle(hThread); // 必须关闭句柄! ``` #### 三、关键注意事项 1. **与CreateThread的区别** `_beginthreadex`会初始化C运行时库的线程本地存储(如`errno`变量),避免直接使用`CreateThread`导致的内存泄漏[^2] 2. **参数传递技巧** 传递多个参数时建议使用结构体: ```cpp struct ThreadParams { int id; const char* name; }; // 调用时: ThreadParams params{1, "Worker"}; _beginthreadex(..., &params, ...); ``` 3. **异常处理** 建议在工程设置中启用`/MD`或`/MDd`运行时库,避免静态链接时的线程安全问题 #### 四、完整示例 ```cpp #include <process.h> #include <windows.h> #include <iostream> unsigned __stdcall MyThread(void* pParam) { int* pVal = static_cast<int*>(pParam); std::cout << "Received value: " << *pVal << std::endl; delete pVal; // 释放堆内存 return 0; } int main() { int* pData = new int(100); // 动态分配传参 HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, MyThread, pData, 0, NULL ); if (hThread) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值