最好了解以下内容
CreateRemoteThread 函数HANDLE CreateThread(
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] SIZE_T dwStackSize,
[in] LPTHREAD_START_ROUTINE lpStartAddress,
[in, optional] __drv_aliasesMem LPVOID lpParameter,
[in] DWORD dwCreationFlags,
[out, optional] LPDWORD lpThreadId
);
参数说明
CREATE_SUSPENDED 表示线程创建后进入挂起状态,直到 ResumeThread 函数调用【注】in 表示输入参数,out 表示输出参数,optional 表示参数可选
【注】即使 lpStartAddress 指向数据、代码或不可访问的区域,CreateThread 也可能会执行成功
【注】如果多线程要调用 CRT,则应该使用 _beginthreadex 函数来创建线程,同时它具有更高的安全性
#include
#include
#define HANDLENUM 5
// function declaration
DWORD WINAPI MyThreadFunction(LPVOID lpParam);
// pass paramter
typedef struct PassValue{
int val1;
int val2;
}PASSVALUE, *PPASSVALUE;
void m_CreateThread()
{
HANDLE aHandleArray[HANDLENUM];
DWORD adwThreadID[HANDLENUM]; // receive thread descriptor
// fill paramter
PASSVALUE pv{
1,
2
};
// create threads
for (int i = 0; i < HANDLENUM; i++)
{
aHandleArray[i] = CreateThread(NULL, 0, MyThreadFunction, &pv, 0, &adwThreadID[i]);
}
// omit error handling ...
// wait for all thread execution completed
WaitForMultipleObjects(HANDLENUM, aHandleArray, TRUE, INFINITE);
printf("所有线程执行完毕\n");
// close handle
for (int i = 0; i < HANDLENUM; i++)
{
CloseHandle(aHandleArray[i]);
}
}
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
PASSVALUE *pv = (PASSVALUE *)lpParam;
printf("thread id is %d, pass paramter one is: %d, pass paramter two is: %d\n", GetCurrentThreadId(), pv->val1, pv->val2);
return 0;
}
执行结果
thread id is 23408, pass paramter one is: 1, pass paramter two is: 2
thread id is 24404, pass paramter one is: 1, pass paramter two is: 2
thread id is 13612, pass paramter one is: 1, pass paramter two is: 2
thread id is 33796, pass paramter one is: 1, pass paramter two is: 2
thread id is 8032, pass paramter one is: 1, pass paramter two is: 2
所有线程执行完毕
_beginthread 与其属于同一类方式,这里不单独说明
_beginthreadex 与 CreateThread 的区别:_beginthreadex 相较来说更加的安全,不会产生内存泄漏,在 _beginthreadex 的源码中,实际是对 CreateThread 进行了封装,所以你可以看到它们的参数几乎是通用的uintptr_t _beginthreadex( // NATIVE CODE
void *security,
unsigned stack_size,
unsigned ( __stdcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
参数解释:
CreateThread 中的就不一样了,要用它的来定义该部分代码仅对 CreateThread 中的实例做了很小的修改即可运行
#include
#include
#include /* _beginthread, _endthread */
#define HANDLENUM 5
unsigned __stdcall MyThreadFunction(void *lpParam);
// pass paramter
typedef struct PassValue {
int val1;
int val2;
}PASSVALUE, *PPASSVALUE;
void m_beginthreadex()
{
HANDLE aHandleArray[HANDLENUM];
unsigned int adwThreadID[HANDLENUM]; // receive thread descriptor
// fill paramter
PASSVALUE pv{
1,
2
};
// create threads
for (int i = 0; i < HANDLENUM; i++)
{
aHandleArray[i] = (HANDLE)_beginthreadex(NULL, 0, MyThreadFunction, &pv, 0, &adwThreadID[i]);
}
// omit error handling ...
// wait for all thread execution completed
WaitForMultipleObjects(HANDLENUM, aHandleArray, TRUE, INFINITE);
printf("所有线程执行完毕\n");
// close handle
for (int i = 0; i < HANDLENUM; i++)
{
CloseHandle(aHandleArray[i]);
}
}
unsigned __stdcall MyThreadFunction(void *lpParam)
{
PASSVALUE *pv = (PASSVALUE *)lpParam;
printf("thread id is %d, pass paramter one is: %d, pass paramter two is: %d\n", GetCurrentThreadId(), pv->val1, pv->val2);
return 0;
}
执行结果
thread id is 1920, pass paramter one is: 1, pass paramter two is: 2
thread id is 11760, pass paramter one is: 1, pass paramter two is: 2
thread id is 2896, pass paramter one is: 1, pass paramter two is: 2
thread id is 6556, pass paramter one is: 1, pass paramter two is: 2
thread id is 29496, pass paramter one is: 1, pass paramter two is: 2
所有线程执行完毕
有四种终止运行线程的方式
ExitThread 或者 _endthreadex 函数杀死自己,也就是与创建线程对应的函数DWORD WaitForMultipleObjects(
[in] DWORD nCount,
[in] const HANDLE *lpHandles,
[in] BOOL bWaitAll,
[in] DWORD dwMilliseconds
);
我们将 CreateThread 小节中实例的代码修改如下部分,以演示 bWaitAll 设置为 FLASE 的效果
bWaitAll 设置为 FLASE 表示只要有一个线程触发信号则 WaitForMultipleObjects 函数执行完成当 bWaitAll 设置为 TRUE 时,“所有线程执行完毕” 这句话始终出现在输出语句的结尾,而当 bWaitAll 设置为 FLASE 其效果如下

可以看到,该语句将不会在最后出现。
【注】当如果你只用等待一个信号的时候,可以使用 WaitForSingleObject