首先谈到在C++中创建线程的方法,CSDN 2010版介绍如下:
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, //安全属性,一般设置为NULL即可
_In_ SIZE_T dwStackSize, //一般设置为0就可
_In_ LPTHREAD_START_ROUTINE lpStartAddress, //程序入口地址,这就是问题的重点
_In_opt_ LPVOID lpParameter, //可以传入的任意指针变量,可以好好利用
_In_ DWORD dwCreationFlags, //该变量确定线程是否即可运行,为0即可运行,
//为CREATE_SUSPENDED则挂起
_Out_opt_ LPDWORD lpThreadId //输出ID,可以直接传入NULL
);
在此主要关注参数 LPTHREAD_START_ROUTINE lpStartAddress,其类型 LPTHREAD_START_ROUTINE定义为如下:
DWORD (WINAPI *PTHREAD_START_ROUTINE)(
LPVOID lpThreadParameter
);
因为必须指定为WINAPI函数调用类型,即_stdcall,但是作为C++内成员函数,其函数类型为thiscall,故不满足要求。
解决方法有多种,下面介绍一下其中之二:
- 将其声明为静态成员函数,即声明为static DWORD WINAPI ThreadFun(LPVOID *lParam);此时函数调用类型变为了_stdcall,满足要求。但是问题出现了,静态成员函数是只能访问类的静态成员,不能访问其他成员的。因为静态成员函数被调用时可能类的对象还没有创建,如果能够保证调用时类对象已建立,则可以使用lpParameter传入this指针,在ThreadFun中将其强制转换为类对象指针类型,用于访问普通成员及成员函数。但是个人在实践中发现这种方法是存在问题的()。
2.不定义类成员函数为线程函数,而将线程函数定义为类的友元函数。这样,线程函数也可以有类成员函数同等的权限,并且函数调用类型为_stdcall,满足所有要求,能够解决方法1中存在的一些bug;
具体实现方法可参考: http://blog.163.com/lyz_sea/blog/static/115586707201101025443711/