详细分析

详细分析

书籍:《Visual C++ 2017从入门到精通》

环境:Visual Studio 2022

内容:[例8.16]利用_beginthread不断创建线程

1. 函数来源与用途​​

​​_beginthread()​​ 和 ​​_endthread()​​ 是 ​​C运行时库(CRT)​​ 提供的线程管理函数,主要用于简化线程的创建和终止过程。​​_beginthread()​​:创建并启动一个新线程,自动初始化与C运行时库相关的资源(如线程局部存储)。​​_endthread()​​:终止当前线程,并释放相关资源。

​​2. 函数原型与参数​​

​​2.1 _beginthread()​​

uintptr_t _beginthread(

void( *start_address )( void * ), // 线程入口函数

unsigned stack_size, // 线程栈大小(默认为1MB)

void *arglist // 传递给线程函数的参数

);

​​返回值​​:线程句柄(HANDLE),失败时返回 -1。​​特点​​:

自动分配线程栈空间(若 stack_size 为0)。初始化C运行时库的线程数据(如 errno、文件流等)。​​必须​​与 _endthread() 配合使用。

​​2.2 _endthread()​​

void _endthread( void );

​​作用​​:终止当前线程,释放资源。​​调用方式​​:通常在线程函数末尾隐式调用,也可显式调用。

​​3. 工作流程​​

​​3.1 使用 _beginthread() 创建线程​​

#include

unsigned __stdcall ThreadFunc(void* param) {

// 线程逻辑

_endthread(); // 显式终止线程(可选)

return 0;

}

int main() {

uintptr_t hThread = _beginthread(ThreadFunc, 0, NULL);

if (hThread == -1) {

// 错误处理

}

WaitForSingleObject((HANDLE)hThread, INFINITE); // 等待线程结束

CloseHandle((HANDLE)hThread);

return 0;

}

​​3.2 线程终止​​

​​隐式终止​​:线程函数执行完毕时,自动调用 _endthread()。​​显式终止​​:在任意位置调用 _endthread(),但需确保资源已释放。

​​4. 与 CreateThread 的区别​​

​​特性​​​​_beginthread()​​​​CreateThread​​​​所属库​​C运行时库(CRT)Windows API​​栈初始化​​自动分配和初始化栈需手动指定栈大小​​运行时库兼容性​​初始化CRT数据(如 errno)不初始化CRT数据​​线程局部存储(TLS)​​自动分配需手动处理​​异常处理​​支持C++异常需通过结构化异常处理(SEH)

​​5. 关键注意事项​​

​​5.1 必须配对使用​​

若使用 _beginthread() 创建线程,必须在线程函数中调用 _endthread(),否则可能导致资源泄漏(如未释放的文件句柄)。

​​5.2 栈大小管理​​

默认栈大小为1MB,可通过 stack_size 参数调整。过小的栈可能导致栈溢出,过大会浪费内存。

​​5.3 线程函数签名​​

线程函数必须符合 void (*)(void*) 格式,返回类型为 unsigned __stdcall。

​​5.4 与C++的兼容性​​

_beginthread() 不支持C++异常,若需使用C++异常,应改用 _beginthreadex()(Windows API扩展)。

​​6. 示例代码:多线程求和​​

#include

#include

unsigned __stdcall SumThread(void* param) {

int* data = (int*)param;

int sum = 0;

for (int i = 0; i < 100; i++) {

sum += data[i];

}

printf("Sum: %d

", sum);

_endthread();

return 0;

}

int main() {

int data[100];

for (int i = 0; i < 100; i++) {

data[i] = i + 1;

}

uintptr_t hThread = _beginthread(SumThread, 0, data);

if (hThread == -1) {

printf("Failed to create thread.

");

return 1;

}

WaitForSingleObject((HANDLE)hThread, INFINITE);

CloseHandle((HANDLE)hThread);

return 0;

}

​​7. 替代方案与现代实践​​

​​推荐使用 std::thread​​:C++11及以上版本提供了跨平台的线程库,无需依赖CRT。​​使用 _beginthreadex()​​:若需更精细的控制(如返回线程ID),可使用Windows API的 _beginthreadex()。

​​8. 总结​​

​​_beginthread()​​ 和 ​​_endthread()​​ 是CRT提供的简化线程管理工具,适合快速开发小型多线程程序。​​优点​​:自动初始化CRT资源,简化线程创建。​​缺点​​:功能有限,不适合复杂场景(如C++异常、跨平台开发)。​​适用场景​​:Windows平台下的简单多线程任务,或与C标准库深度集成的项目。

实际开发中,建议优先使用C++11的 std::thread 或Windows API的 CreateThread,以获得更好的灵活性和可维护性。

相关阅读

365bet官网体育投注 身份证怎么扫描?归纳了三种扫描方法

身份证怎么扫描?归纳了三种扫描方法

365bet导航 注销的手机号码多久会被再次出售

注销的手机号码多久会被再次出售

365bet官网体育投注 现场手记|2022世界杯,美伊“生死战”中的温情侧面

现场手记|2022世界杯,美伊“生死战”中的温情侧面

365提款验证地址是什么 免费财务软件哪个好:2025年中小企业选型指南与四大王牌推荐

免费财务软件哪个好:2025年中小企业选型指南与四大王牌推荐

365提款验证地址是什么 简报专题页

简报专题页

365bet官网体育投注 锦湖769轮胎 锦湖769轮胎质量怎么样

锦湖769轮胎 锦湖769轮胎质量怎么样

365bet导航 衣服的画法by:ノギビ - 优动漫绘画教学-软件教学

衣服的画法by:ノギビ - 优动漫绘画教学-软件教学

365bet导航 魔域手游怎么去神界

魔域手游怎么去神界

365bet导航 斲户是什么意思

斲户是什么意思