DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
功能说明:
等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止.
hHandle:
内核对象句柄,可以是进程也可以是线程.
dwMilliseconds:
等待时间,单位是毫秒 INFINITE(-1)一直等待
返回值:
WAIT_OBJECT_0(0) 等待对象变为已通知
WAIT_TIMEOUT(0x102) 超时
特别说明:
1、内核对象中的每种对象都可以说是处于已通知或未通知的状态之中
2、这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的
3、当线程正在运行的时候,线程内核对象处于未通知状态
4、当线程终止运行的时候,它就变为已通知状态
5、在内核中就是个BOOL值,运行时FALSE 结束TRUE
代码演示:
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
for(int i=0;i<5;i++)
{
printf("+++++++++
");
Sleep(1000);
}
return 0;
}
int main(int argc, char* argv[])
{
//创建一个新的线程
HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,
NULL, 0, NULL);
DWORD dwCode = ::WaitForSingleObject(hThread1, INFINITE);
MessageBox(0,0,0,0);
return 0;
}
DWORD WaitForMultipleObjects(
DWORD nCount, // number of handles in array
CONST HANDLE *lpHandles, // object-handle array
BOOL bWaitAll, // wait option
DWORD dwMilliseconds // time-out interval
);
功能说明:
同时查看若干个内核对象的已通知状态
nCount:
要查看内核对象的数量
lpHandles:
内核对象数组
bWaitAll:
等到类型 TRUE 等到所有变为已通知 FALSE 只要有一个变为已通知
dwMilliseconds:
超时时间
INFINITE一直等待
返回值:
bWaitAll为TRUE时,返回WAIT_OBJECT_0(0) 代码所以内核对象都变成已通知
bWaitAll为FALSE时,返回最先变成已通知的内核对象在数组中的索引
WAIT_TIMEOUT(0x102) 超时
代码演示:
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
for(int i=0;i<5;i++)
{
printf("+++++++++
");
Sleep(1000);
}
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
for(int i=0;i<3;i++)
{
printf("---------
");
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;
}
进程一:
HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");
进程二:
HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
WaitForSingleObject(g_hMutex,INFINITE);
//逻辑代码
ReleaseMutex(g_hMutex);
进程三:
HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
WaitForSingleObject(g_hMutex,INFINITE);
//逻辑代码
ReleaseMutex(g_hMutex);
互斥体与临界区的区别:
1、临界区只能用于单个进程间的线程控制.
2、互斥体可以设定等待超时,但临界区不能.
3、线程意外终结时,Mutex可以避免无限等待.
4、Mutex效率没有临界区高.
以下是抢红包程序:
// hongbao.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #include<stdio.h> HWND hEdit1; HWND hEdit2; HWND hEdit3; HWND hEdit4; HANDLE hMutex; int num = 1000; DWORD WINAPI ProcThread1(LPVOID lpParameter) { TCHAR szBuff[10] = {0}; int flag = 0; HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "XYZ"); while(num >= 50) { WaitForSingleObject(hMutex, INFINITE); // GetWindowText(hEdit1, szBuff, 10); // sscanf(szBuff, "%d", &flag); num -= 50; flag += 50; sprintf(szBuff, "%d", num); SetWindowText(hEdit1, szBuff); memset(szBuff, 0, 10); sprintf(szBuff, "%d", flag); SetWindowText(hEdit2, szBuff); ExitThread(2); ReleaseMutex(hMutex); Sleep(1000); } return 0; } DWORD WINAPI ProcThread2(LPVOID lpParameter) { TCHAR szBuff[10] = {0}; int flag = 0; HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "XYZ"); while(num >= 50) { WaitForSingleObject(hMutex, INFINITE); // GetWindowText(hEdit1, szBuff, 10); // sscanf(szBuff, "%d", &flag); num -= 50; flag += 50; sprintf(szBuff, "%d", num); SetWindowText(hEdit1, szBuff); memset(szBuff, 0, 10); sprintf(szBuff, "%d", flag); SetWindowText(hEdit3, szBuff); ReleaseMutex(hMutex); Sleep(2000); } return 0; } DWORD WINAPI ProcThread3(LPVOID lpParameter) { TCHAR szBuff[10] = {0}; int flag = 0; HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "XYZ"); while(num >= 50) { WaitForSingleObject(hMutex, INFINITE); // GetWindowText(hEdit1, szBuff, 10); // sscanf(szBuff, "%d", &flag); num -= 50; flag += 50; sprintf(szBuff, "%d", num); SetWindowText(hEdit1, szBuff); memset(szBuff, 0, 10); sprintf(szBuff, "%d", flag); SetWindowText(hEdit4, szBuff); ReleaseMutex(hMutex); Sleep(3000); } return 0; } DWORD WINAPI ProcThread(LPVOID lpParameter) { hMutex = CreateMutex(NULL, FALSE, "XYZ"); HANDLE hHandleArr[3]; hHandleArr[0] = ::CreateThread(NULL, 0, ProcThread1, NULL, 0, NULL); hHandleArr[1] = ::CreateThread(NULL, 0, ProcThread2, NULL, 0, NULL); hHandleArr[2] = ::CreateThread(NULL, 0, ProcThread3, NULL, 0, NULL); ::WaitForMultipleObjects(3, hHandleArr, TRUE, INFINITE); ::CloseHandle(hMutex); return 0; } BOOL CALLBACK ProcDialog(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: hEdit1 = GetDlgItem(hwnd, IDC_EDIT1); SetWindowText(hEdit1, "1000"); hEdit2 = GetDlgItem(hwnd, IDC_EDIT2); SetWindowText(hEdit2, "0"); hEdit3 = GetDlgItem(hwnd, IDC_EDIT3); SetWindowText(hEdit3, "0"); hEdit4 = GetDlgItem(hwnd, IDC_EDIT4); SetWindowText(hEdit4, "0"); break; case WM_CLOSE: EndDialog(hwnd, 0); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BUTTON1: HANDLE hThread = ::CreateThread(NULL, 0, ProcThread, NULL, 0, NULL); ::CloseHandle(hThread); return TRUE; } break; } return FALSE; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, ProcDialog); return 0; }