CreateThread创建线程传递结构体参数
一般mfc创建线程的函数用的最多的有两个:AfxBeginThread和CreateThread。首先来学习CreateThread。
CreateThread线程函数及参数如下:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes
DWORD dwStackSize, // initial thread stack size
LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
LPVOID lpParameter, // argument for new thread
DWORD dwCreationFlags, // creation flags
LPDWORD lpThreadId // pointer to receive thread ID
);
第一个参数是指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL。
第二个参数是用于新线程的初始堆栈大小,默认值为0。在任何情况下,Windows根据需要动态延长堆栈的大小。
第三个参数是线程函数的名称。函数名称没有限制,但是最好以以下列形式声明:
DWORD WINAPI ThreadProc (LPVOID pParam) ;
第四个参数为传递给ThreadProc的参数。这样主线程和从属线程就可以共享数据。
第五个参数通常为0,但当建立的线程不马上执行时为旗标CREATE_SUSPENDED。线程将暂停直到呼叫ResumeThread来恢复线程的执行为止。
第六个参数是一个指标,指向接受执行绪ID值的变量。
函数介绍完成后,接下来要做的是如何把结构体变量传递到线程执行函数当中。有时候两个线程之间需要共享的数据比较多,那么用结构体来传递数据时必然的选择。
首先声明一个结构体ThreadPrameter:
struct ThreadParameter{
int id;
char name[20];
};
然后在创建线程之前生成一个结构体实例:
ThreadParameter tp;
tp.id = 1;
char name[20];
name = "tom";
tp.name = name;
然后开始创建线程,将结构体的指针添加到函数里面:
HANDLE threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFuncion,&tp,0,NULL);
注意:第三个参数之前的 LPTHREAD_START_ROUTINE一定要加上,不然会报错。
最后完成线程函数ThreadFunction:
DWORD WINAPI ThreadFunction (LPVOID pParam) {
//强制转换参数
ThreadParameter *tp = (ThreadParmeter *)pParam;
//接下来就可以对传进来的结构体进行操作了
//tp->id;
//tp->name;
}
最后别忘了程序退出时CloseHandle(threadhandle);
附:
--------------------
问题:
用VC创建新线程易出的问题error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned long (__stdcall *)(void *)'
解决方案:
(1)如果线程要执行的是类的成员函数,则必须用static声明为静态函数
如:
class echo
{
static DWORD WINAPI ThreadFunc(LPVOID pvoid)
......
......
}
(2)一般都是调用全局函数.
我们在用CreateThread(NULL,0,ThreadProc,NULL,0,NULL)创建线程得时候,此函数中需要新线程中的函数地 址,我们常用的有两种方法解决:
一.将我们要调用的新线程函数声明成DWORD WINAPI ThreadProc(lpvoid lpParameter)。
二.我们可以将新线程函数声明成类中的成员函数:static DWORD WINAPI ThreadProc(lpvoid lpParameter)
但是当我们的写法不正确的时候,往往会出现error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned long (__stdcall *)(void *)' 这个问题,另我们这些初学者很是恼火,现将可能出现的这种情况列举如下:
第一种方法的使用是将新线程要处理的函数写在类外的一种的情况也就是全局函数,非类成员函数,需要注意的就是在创建新线程之前要声明该函数或定义函数,要 注意这时不要在该类的头文件添加该函数的声明(我就犯过这样的错误)。记住用完要释放哦!
第二种方法的使用是将新线程中要处理的函数定义成本类中的成员,使用时要注意一定要吧该函数声明成static类型的,否则就会报错error C2664。