书籍:《Visual C++ 2017从入门到精通》
环境:Visual Studio 2022
内容:[例8.18]_beginthreadex函数的简单示例
1. 函数来源与用途
_beginthreadex() 和 _endthreadex() 是 C运行时库(CRT) 提供的线程管理函数,用于创建和终止线程,并自动初始化与C运行时相关的资源(如线程局部存储、errno 等)。_beginthreadex():创建并启动一个新线程,返回线程句柄。_endthreadex():终止当前线程,释放相关资源。
2. 函数原型与参数
2.1 _beginthreadex()
uintptr_t _beginthreadex(
void *security_descriptor, // 安全属性(通常为NULL)
unsigned stack_size, // 线程栈大小(默认为1MB)
unsigned (WINAPI *start_address)(void *), // 线程入口函数
void *arglist, // 传递给线程函数的参数
unsigned initflag, // 创建标志(如CREATE_SUSPENDED)
unsigned *thrdaddr // 返回线程ID
);
返回值:线程句柄(HANDLE),失败时返回 0。特点:
自动分配线程栈空间(若 stack_size 为0)。初始化C运行时库的线程数据(如 errno、文件流、TLS)。需与 _endthreadex() 配合使用。
2.2 _endthreadex()
void _endthreadex(unsigned retcode);
参数:retcode 是线程的退出代码。作用:终止当前线程,释放资源。调用方式:通常在线程函数末尾隐式调用,也可显式调用。
3. 工作流程
3.1 使用 _beginthreadex() 创建线程
#include
unsigned __stdcall ThreadFunc(void* param) {
// 线程逻辑
_endthreadex(0); // 显式终止线程(可选)
return 0;
}
int main() {
uintptr_t hThread = _beginthreadex(NULL, 0, ThreadFunc, NULL, 0, NULL);
if (hThread == 0) {
// 错误处理
}
WaitForSingleObject((HANDLE)hThread, INFINITE); // 等待线程结束
CloseHandle((HANDLE)hThread);
return 0;
}
3.2 线程终止
隐式终止:线程函数执行完毕时,自动调用 _endthreadex()。显式终止:在任意位置调用 _endthreadex(),但需确保资源已释放。
4. 与 CreateThread 的区别
特性_beginthreadex()CreateThread所属库C运行时库(CRT)Windows API栈初始化自动分配和初始化栈需手动指定栈大小运行时库兼容性初始化CRT数据(如 errno)不初始化CRT数据线程局部存储(TLS)自动分配需手动处理异常处理支持C++异常需通过结构化异常处理(SEH)
5. 关键注意事项
5.1 必须配对使用
若使用 _beginthreadex() 创建线程,必须在线程函数中调用 _endthreadex(),否则可能导致资源泄漏(如未释放的文件句柄)。
5.2 栈大小管理
默认栈大小为1MB,可通过 stack_size 参数调整。过小的栈可能导致栈溢出,过大会浪费内存。
5.3 线程函数签名
线程函数必须符合 unsigned __stdcall (void*) 格式,返回类型为 unsigned int。
5.4 与C++的兼容性
_beginthreadex() 支持C++异常,若需使用C++异常,应优先选择此函数。
6. 示例代码:多线程求和
#include
#include
unsigned __stdcall SumThread(void* param) {
int* data = (int*)param;
unsigned int sum = 0;
for (int i = 0; i < 100; i++) {
sum += data[i];
}
printf("Sum: %u
", sum);
_endthreadex(sum); // 显式传递退出代码
return sum;
}
int main() {
int data[100];
for (int i = 0; i < 100; i++) {
data[i] = i + 1;
}
uintptr_t hThread = _beginthreadex(NULL, 0, SumThread, data, 0, NULL);
if (hThread == 0) {
printf("Failed to create thread.
");
return 1;
}
WaitForSingleObject((HANDLE)hThread, INFINITE);
CloseHandle((HANDLE)hThread);
return 0;
}
7. 替代方案与现代实践
推荐使用 std::thread:C++11及以上版本提供了跨平台的线程库,无需依赖CRT。使用 _beginthread():若需更轻量级的线程创建(但需手动管理CRT资源)。
8. 总结
_beginthreadex() 和 _endthreadex() 是CRT提供的线程管理工具,适合需要与C运行时库深度集成的项目。优点:自动初始化CRT资源(如TLS、errno),简化线程创建。缺点:功能有限,不适合复杂场景(如跨平台开发)。适用场景:Windows平台下的多线程任务,或与C标准库紧密集成的项目。
实际开发中,建议优先使用C++11的 std::thread 或Windows API的 CreateThread,以获得更好的灵活性和可维护性。