书籍:《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 <process.h>
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 <process.h>
#include <stdio.h>
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
,以获得更好的灵活性和可维护性。