循环创建多线程时保证参数的有效性
当我们需要在一个循环中传递参数时,使用使用函数的方法一般都是:
for(int I=0;I <100;I++)
{
fun(I); //使用函数传递i
}
每一个循环都会等待fun(I);函数执行完后再进行下一个循环。
但是当我们需要这个循环中创建线程,并将I的参数传递给线程时,如依然使用以上方法,会造成什么情况呢?
DWORD WINAPI ThreadFun(LPVOID lpParam)
{ //线程函数
Int *I = (int *)lpParam; Return 0;
}
int I;
for(I=0;I <100;I++)
{
DWORD dwThreadId; HANDLE hThread;
hThread = CreateThread(NULL,0,ThreadFunc,&I,0,&dwThreadId);
}
好了,到这里我们就可以发现,在循环中,我们创建线程并传递的参数是I=1后,主程序有可能在执到下一次循环时,第一次的ThreadFun函数仍未执行,而此时的I已经等2了,如果ThreadFun再来调用
Int *I = (int *)lpParam;语句时,显然不是我们想要的结果。
解决此问题的一种方法,便是可以使用静态数组来保存所要传递的参数。
如下:
int I;
static int nPara[100]; //此句需定义为全局
for(I=0;I <100;I++)
{
DWORD dwThreadId;
HANDLE hThread;
NPara[I]=I; //保存参数
hThread = CreateThread(NULL,0,ThreadFunc,&nPara[I],0,&dwThreadId);
}
此时,所有参数均保存在nPara数组中,刚才的问题是解决了。
接下来又有了新的问题,让我们一起来看看吧:
1、如果需要创建的线程不止100,而是非常的大,而且我们也并不知道会有多少次循环的时侯。
2、如果我们需要传递的参数不单单只是一个int型的I,而是一个类。那么我们声明的时侯
(假设线程数量最大为65535)则:
static CMYClass myClass[65535];
编译之后,得到的文件将会堆上一大堆的垃圾。相信任何一位程序都不想看到自己的程序上面堆了一堆垃圾在上面吧。 那么,还有没有更好的办法解决呢。答案是一定的,这里,我就讲一下我自己常用的方法:动态创建对像传递参数。
一提到动态创建,我们自然会想到new 与 delete ,
对了,我想说的也正是他们的使用。
假设参数类型为:
typedef struct _PARA
{
int I;
DWORD dwNumber;
HWND hOther;
}Para;
使用new在堆栈中申请一遍空间,在使用完后必需使用delete将其释放。
int I;
for(I=0;I <100;I++)
{
DWORD dwThreadId;
HANDLE hThread;
Para *myPara = new Para;
MyPara-> I = I; MyPara-> dwNumber = 0 ;//自定
MyPara -> hOther = GetSafeHWnd();//当前窗体句柄
hThread = CreateThread(NULL,0,ThreadFunc,myPara,0,&dwThreadId); //线程函数
}
DWORD WINAPI ThreadFun(LPVOID lpParam)
{
//线程函数
Para *myPara = (Para *)lpParam; //执行其他功能
delete [] myPara; //释放
Return 0;
}
这样的话,也就不怕传递的参数多少与线程的数量太大了。另外如有需要的话可以加上一个线程计数器,保证当前线程的最大数量。
通常情况,我比较喜欢把线程处理放在一个类中处理,在主程序中尽量不与线程打交道。
在循环中使用new 可以保证每次申请到的内存的地址不会是同一个(即不会重复),从而传递给每个线程的参数也互不冲突,互不干扰,相互独立,在线程内部使用完参数后,根据接收的地址,使用delete释放申请的内存块。
用结构,然后将结构的指针传给CreateThread()的参数lpParameter。需要 注意:
结构应该是“静态的”或是“全局的”或者是“动态分配的”。
如果使用局部 变量,有可能在线程调用这个结构时,结构已经不在栈中了。
struct StructA
{
int n1, n2, n3, n4, n5;
};
DWORD WINAPI ThreadFun(LPVOID* param)
{
StructA* pa = (StructA*)param; //这儿就可以访问结构中的变量了
//...... return 1;
}
void TestFunc()
{
DWORD dwID;
//下面的写法不对
StructA a;
CreateThread(NULL, 0, ThreadFun, &a, 0, &dwID);
//下面的写法是对的
static StructA a;
CreateThread(NULL, 0, ThreadFun, &a, 0, &dwID);
}
当我们需要在一个循环中传递参数时,使用使用函数的方法一般都是:
for(int I=0;I <100;I++)
{
fun(I); //使用函数传递i
}
每一个循环都会等待fun(I);函数执行完后再进行下一个循环。
但是当我们需要这个循环中创建线程,并将I的参数传递给线程时,如依然使用以上方法,会造成什么情况呢?
DWORD WINAPI ThreadFun(LPVOID lpParam)
{ //线程函数
Int *I = (int *)lpParam; Return 0;
}
int I;
for(I=0;I <100;I++)
{
DWORD dwThreadId; HANDLE hThread;
hThread = CreateThread(NULL,0,ThreadFunc,&I,0,&dwThreadId);
}
好了,到这里我们就可以发现,在循环中,我们创建线程并传递的参数是I=1后,主程序有可能在执到下一次循环时,第一次的ThreadFun函数仍未执行,而此时的I已经等2了,如果ThreadFun再来调用
Int *I = (int *)lpParam;语句时,显然不是我们想要的结果。
解决此问题的一种方法,便是可以使用静态数组来保存所要传递的参数。
如下:
int I;
static int nPara[100]; //此句需定义为全局
for(I=0;I <100;I++)
{
DWORD dwThreadId;
HANDLE hThread;
NPara[I]=I; //保存参数
hThread = CreateThread(NULL,0,ThreadFunc,&nPara[I],0,&dwThreadId);
}
此时,所有参数均保存在nPara数组中,刚才的问题是解决了。
接下来又有了新的问题,让我们一起来看看吧:
1、如果需要创建的线程不止100,而是非常的大,而且我们也并不知道会有多少次循环的时侯。
2、如果我们需要传递的参数不单单只是一个int型的I,而是一个类。那么我们声明的时侯
(假设线程数量最大为65535)则:
static CMYClass myClass[65535];
编译之后,得到的文件将会堆上一大堆的垃圾。相信任何一位程序都不想看到自己的程序上面堆了一堆垃圾在上面吧。 那么,还有没有更好的办法解决呢。答案是一定的,这里,我就讲一下我自己常用的方法:动态创建对像传递参数。
一提到动态创建,我们自然会想到new 与 delete ,
对了,我想说的也正是他们的使用。
假设参数类型为:
typedef struct _PARA
{
int I;
DWORD dwNumber;
HWND hOther;
}Para;
使用new在堆栈中申请一遍空间,在使用完后必需使用delete将其释放。
int I;
for(I=0;I <100;I++)
{
DWORD dwThreadId;
HANDLE hThread;
Para *myPara = new Para;
MyPara-> I = I; MyPara-> dwNumber = 0 ;//自定
MyPara -> hOther = GetSafeHWnd();//当前窗体句柄
hThread = CreateThread(NULL,0,ThreadFunc,myPara,0,&dwThreadId); //线程函数
}
DWORD WINAPI ThreadFun(LPVOID lpParam)
{
//线程函数
Para *myPara = (Para *)lpParam; //执行其他功能
delete [] myPara; //释放
Return 0;
}
这样的话,也就不怕传递的参数多少与线程的数量太大了。另外如有需要的话可以加上一个线程计数器,保证当前线程的最大数量。
通常情况,我比较喜欢把线程处理放在一个类中处理,在主程序中尽量不与线程打交道。
在循环中使用new 可以保证每次申请到的内存的地址不会是同一个(即不会重复),从而传递给每个线程的参数也互不冲突,互不干扰,相互独立,在线程内部使用完参数后,根据接收的地址,使用delete释放申请的内存块。
用结构,然后将结构的指针传给CreateThread()的参数lpParameter。需要 注意:
结构应该是“静态的”或是“全局的”或者是“动态分配的”。
如果使用局部 变量,有可能在线程调用这个结构时,结构已经不在栈中了。
struct StructA
{
int n1, n2, n3, n4, n5;
};
DWORD WINAPI ThreadFun(LPVOID* param)
{
StructA* pa = (StructA*)param; //这儿就可以访问结构中的变量了
//...... return 1;
}
void TestFunc()
{
DWORD dwID;
//下面的写法不对
StructA a;
CreateThread(NULL, 0, ThreadFun, &a, 0, &dwID);
//下面的写法是对的
static StructA a;
CreateThread(NULL, 0, ThreadFun, &a, 0, &dwID);
}