创建在调用进程的虚拟地址空间内执行的线程。
若要创建在另一个进程的虚拟地址空间中运行的线程,请使用CreateRemoteThread
函数。
函数声明
1 2 3 4 5 6 7 8 9 10 11 12
| WINBASEAPI _Ret_maybenull_ HANDLE WINAPI CreateThread( _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ SIZE_T dwStackSize, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ __drv_aliasesMem LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD lpThreadId );
|
参数
lpThreadAttributes
指向SECURITY_ATTRIBUTES
结构的指针, 该结构确定是否可由子进程继承返回的句柄。如果lpThreadAttributes
为NULL
, 则无法进程句柄;
dwStackSize
堆栈的初始大小(以字节为单位)。系统将此值舍入到最近的页面。如果此参数为零, 则新线程将使用可执行文件的默认大小;
lpStartAddress
指向要由线程执行的应用程序定义函数的指针。此指针表示线程的起始地址;
lpStartAddress
函数原型1 2 3
| DWORD WINAPI ThreadProc( _In_ LPVOID lpParameter );
|
lpParameter
指向要传递给线程的变量的指针;
dwCreationFlags
控制线程的标志
值 |
含义 |
0 |
线程在创建后立即运行 |
CREATE_SUSPENDED 0x00000004 |
线程以挂起状态创建, 在调用ResumeThread 函数之前不会运行 |
STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 |
dwStackSize 参数指定堆栈的初始保留大小。如果未指定此标志, dwStackSize 将指定提交大小 |
lpThreadId
指向接收线程标识符的变量的指针。如果此参数为NULL
, 则不返回线程标识符;
返回值
如果函数成功, 则返回值是新线程的句柄;
如果函数失败, 则返回值为NULL
;
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| DWORD WINAPI ThreadFirstProc(LPVOID lpParameter) { WCHAR wcBuffer[20]{}; DWORD dwTimer = 0; ::GetWindowText((HWND)lpParameter, wcBuffer, 20); WCHAR wcValue[20]{}; int iValue = _wtoi(wcBuffer); while (iValue > 0) { wsprintf(wcValue, L"%d", --iValue); ::SetWindowText((HWND)lpParameter, wcValue); Sleep(1000); } return 0; }
DWORD WINAPI ThreadSecondProc(LPVOID lpParameter) { WCHAR wcBuffer[20]{}; DWORD dwTimer = 0; ::GetWindowText((HWND)lpParameter, wcBuffer, 20); WCHAR wcValue[20]{}; int iValue = _wtoi(wcBuffer); while (iValue >= 0) { wsprintf(wcValue, L"%d", ++iValue); ::SetWindowText((HWND)lpParameter, wcValue); Sleep(1000); } return 0; }
CWnd* pWndFirst = GetDlgItem(IDC_EDIT1); HWND hWndFirst = pWndFirst->GetSafeHwnd(); CWnd* pWndSecond = GetDlgItem(IDC_EDIT2); HWND hWndSecond = pWndSecond->GetSafeHwnd(); HANDLE hThreadFirst = ::CreateThread(NULL, 0, ThreadFirstProc, hWndFirst, 0, NULL); HANDLE hThreadSecond = ::CreateThread(NULL, 0, ThreadSecondProc, hWndSecond, 0, NULL);
|
WaitForSingleObject
功能说明
等待函数可使线程自愿进入等待状态, 直到一个特定的内核对象变为已通知状态为止;
函数声明
1 2 3 4 5 6 7
| WINBASEAPI DWORD WINAPI WaitForSingleObject( _In_ HANDLE hHandle, _In_ DWORD dwMilliseconds );
|
参数说明
hHandle
内核对象句柄, 可以是进程也可以是线程;
dwMilliseconds
等待时间, 单位是毫秒; INFINITE(-1)
一直等待;
返回值
- WAIT_OBJECT_0(0); 等待对象变为已通知;
- WAIT_TIMEOUT(0x102); 超时;
特别说明
- 内核对象中的每种对象都可以说是处于已通知或未通知的状态之中;
- 这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的;
- 当线程正在运行的时候, 线程内核对象处于未通知状态;
- 当线程终止运行的时候, 它就变为已通知状态;
- 在内核中就是个BOOL值, 运行时FALSE, 结束TRUE;
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| DWORD WINAPI ThreadProc1(LPVOID lpParameter) { for(int i=0;i<5;i++) { printf("+++++++++\n"); Sleep(1000); } return 0; } int main(int argc, char* argv[]) { HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1, DWORD dwCode = ::WaitForSingleObject(hThread1, INFINITE); MessageBox(0,0,0,0); return 0; }
|
函数声明
1 2 3 4 5 6 7 8 9
| WINBASEAPI DWORD WINAPI WaitForMultipleObjects( _In_ DWORD nCount, _In_reads_(nCount) CONST HANDLE* lpHandles, _In_ BOOL bWaitAll, _In_ DWORD dwMilliseconds );
|
参数说明
nCount
要查看内核对象的数量;
lpHandles
内核对象数组
bWaitAll
等待类型; TRUE: 等待所有变为已通知, FALSE: 只要有一个变为已通知;
dwMilliseconds
超时时间; INFINITE
一直等待;
返回值
- bWaitAll为TRUE时, 返回WAIT_OBJECT_0(0)代码所有内核对象都变为已通知;
- bWaitAll为FALSE时, 返回最先变成已通知的内核对象在数组中的索引;
- WAIT_TIMEOUT(0x102), 超时;
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| DWORD WINAPI ThreadProc1(LPVOID lpParameter) { for(int i=0;i<5;i++) { printf("+++++++++\n"); Sleep(1000); } return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParameter) { for(int i=0;i<3;i++) { printf("---------\n"); Sleep(1000); } return 0; } int main(int argc, char* argv[]) { HANDLE hArray[2]; HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL); HANDLE hThread2 = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL); hArray[0] = hThread1; hArray[1] = hThread2; DWORD dwCode = ::WaitForMultipleObjects(2, hArray,FALSE,INFINITE); MessageBox(0,0,0,0); return 0; }
|