标准C运行时库函数,需要包含头文件process.h。
创建线程
uintptr_t _beginthread(
void (__cdecl *start_address)(void* fun),//线程执行函数,__cdecl
unsigned stack_size, //线程的堆栈大小,0,默认大小(1M)
void *arglist //线程执行函数的参数
);
uintptr_t _beginthreadex(
void *security, //安全属性,NULL,默认安全属性
unsigned stack_size, //线程的堆栈大小,0,默认大小(1M)
unsigned (__stdcall *start_address)(void* fun), //线程执行函数,__stdcall
void *arglist, //线程执行函数的参数
unsigned initflag, //线程的初始状态,,0:立即执行;CREATE_SUSPENDED:挂起
unsigned *thrdaddr //返回线程的ID
);
1、_beginthread错误返回-1,_beginthreadex错误返回0。
2、这两个API都可以创建线程,但_beginthreadex比_beginthread更安全些。MSDN上的解释大概是这样的:用_beginthread创建线程时,如果线程执行函数瞬间结束,可导致_beginthread返回线程句柄无效或是另一个线程的句柄。同时,_beginthreadex创建的线程初始状态可以为挂起,这样能更好地控制线程状态。
在执行函数中结束线程
void _endthread(void);
void _endthreadex(unsigned retval);
1、这两个API在线程执行函数中调用,会立即结束线程。若在执行函数外调用,不会结束线程。
2、_endthread和_endthreadex都会释放线程的资源,比如thread local storage(TLS)。但_endthreadex不会释放线程句柄,需要手动调用WIN32API CloseHandle释放。
3、线程执行函数返回后,会自动调用_endthread或_endthreadex。
_endthread或_endthreadex导致的内存泄漏
调用_endthread后,线程执行函数结束。但它没有释放在执行函数中new的内存,同时,对于在函数中定义的类对象,它的析构函数不会执行。举一个例子,如果有个类是这样定义的,在构造函数中new了内存,并在析构函数中释放。很显然,内存泄漏。
代码示例
class MyClass
{
public:
MyClass(){cout << "MyClass enter" << endl;}
~MyClass(){cout << "MyClass exit" << endl;}
};
void fun1(void* param)
{
MyClass mycl;
_endthread();//观察注释这行代码和不注释,的输出结果
}
int main()
{
_beginthread(fun1, 0, NULL);
getchar();
return 0;
}
输出
注释_endthread()时:
MyClass enter
MyClass exit
不注释时:
MyClass enter
不完整的接口
遗憾的是,C运行库没有提供挂起线程和唤醒线程功能。下一步研究WIN32创建线程方法,可以弥补这一点。