承接上一篇:https://blog.csdn.net/uVarAndMethod/article/details/90360838
1、內核對象:
進程、線程、文件、文件映射、事件、互斥體等等
2、事件內核對象的創建
HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");
HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");
3、事件內核對象的獲取
HANDLE OpenEvent(
DWORD dwDesiredAccess, // access
BOOL bInheritHandle, // inheritance option
LPCTSTR lpName // object name
);
HANDLE g_hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "XYZ");
HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");
4、內核對象的銷燬
BOOL CloseHandle(HANDLE hobj);
(1)、當沒有其他程序引用時,系統會銷燬內核對象(使用數量).
(2)、內核對象的生命週期,可能比創建它的對象要長.
5、內核對象的生命週期
eg:CloseHandle()/進程結束
進程一:
HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");
SetEvent(g_hEvent);
進程二:
HANDLE g_hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "XYZ");
WaitForSingleObject(g_hEvent, INFINITE);
eg:內核對象的生命週期
進程一:
HANDLE g_hEvent = CreateEvent(NULL, TRUE, FALSE, "XYZ");
SetEvent(g_hEvent);
進程二:
HANDLE g_hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "XYZ");
WaitForSingleObject(g_hEvent, INFINITE);
///////////////////////////////////////////////////////////////////////////
1、事件對象的創建
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全屬性 NULL時爲系統默認
BOOL bManualReset, // TRUE 通過調用ResetEvent將事件對象標記爲未通知
BOOL bInitialState, // TRUE 已通知狀態 FALSE未通知狀態
LPCTSTR lpName // 對象名稱 以NULL結尾的字符串
);
2、事件對象的控制
BOOL SetEvent(HANDLE hEvent); //將對象設置爲已通知
3、關閉時間對象句柄
//關閉句柄
CloseHandle();
4、線程控制實驗:只讀形式的線程控制
HANDLE g_hEvent;
HWND hEdit1;
HWND hEdit2;
HWND hEdit3;
HWND hEdit4;
HANDLE hThread1;
HANDLE hThread2;
HANDLE hThread3;
HANDLE hThread4;
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
//創建事件
//默認安全屬性 手動設置未通知狀態(TRUE) 初始狀態未通知 沒有名字
g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE hThread[3];
//創建3個線程
hThread[0] = ::CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
hThread[1] = ::CreateThread(NULL, 0, ThreadProc3, NULL, 0, NULL);
hThread[2] = ::CreateThread(NULL, 0, ThreadProc4, NULL, 0, NULL);
//設置文本框的值
SetWindowText(hEdit1,"1000");
//設置事件爲已通知
SetEvent(g_hEvent);
//等待線程結束 銷燬內核對象
WaitForMultipleObjects(3, hThread, TRUE, INFINITE);
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
CloseHandle(hThread[2]);
CloseHandle(g_hEvent);
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
TCHAR szBuffer[10] = {0};
//當事件變成已通知時
WaitForSingleObject(g_hEvent, INFINITE);
//讀取內容
GetWindowText(hEdit1,szBuffer,10);
SetWindowText(hEdit2,szBuffer);
return 0;
}
DWORD WINAPI ThreadProc3(LPVOID lpParameter)
{
TCHAR szBuffer[10] = {0};
//當事件變成已通知時
WaitForSingleObject(g_hEvent, INFINITE);
//讀取內容
GetWindowText(hEdit1,szBuffer,10);
SetWindowText(hEdit3,szBuffer);
return 0;
}
DWORD WINAPI ThreadProc4(LPVOID lpParameter)
{
TCHAR szBuffer[10] = {0};
//當事件變成已通知時
WaitForSingleObject(g_hEvent, INFINITE);
//讀取內容
GetWindowText(hEdit1,szBuffer,10);
SetWindowText(hEdit4,szBuffer);
return 0;
}
////////////////////////////////////////////////////////////////
創建信號量
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
函數說明:
第一個參數表示安全控制,一般直接傳入NULL。
第二個參數表示初始資源數量。0時不發送信號
第三個參數表示最大併發數量。lInitialCount<=lMaximumCount
第四個參數表示信號量的名稱,傳入NULL表示匿名信號量。
打開信號量
HANDLE OpenSemaphore(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
函數說明:
第一個參數表示訪問權限,對一般傳入SEMAPHORE_ALL_ACCESS。詳細解釋可以查看MSDN文檔。
第二個參數表示信號量句柄繼承性,一般傳入FALSE即可。
第三個參數表示名稱,不同進程中的各線程可以通過名稱來確保它們訪問同一個信號量。
遞增信號量的當前資源計數
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
函數說明:
第一個參數是信號量的句柄。
第二個參數表示增加個數,必須大於0且不超過最大資源數量。
第三個參數返回當前資源數量的原始值,設爲NULL表示不需要傳出。
注:沒有一個函數可以用來查詢信標的當前資源數量的值
信號量的清理與銷燬
CloseHandle()
通過信號量控制對資源的訪問:
見MSDN
eg:
信號量應用
#include "stdafx.h"
#include "resource.h"
HANDLE hSemaphore;
HANDLE hThread[3];
HWND hEditSet;
HWND hEdit1;
HWND hEdit2;
HWND hEdit3;
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
TCHAR szBuffer[10];
DWORD dwTimmer=0;
WaitForSingleObject(hSemaphore, INFINITE);
while(dwTimmer<100)
{
Sleep(100);
memset(szBuffer,0,10);
GetWindowText(hEdit1,szBuffer,10);
sscanf( szBuffer, "%d", &dwTimmer );
dwTimmer++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwTimmer);
SetWindowText(hEdit1,szBuffer);
}
ReleaseSemaphore(hSemaphore, 1, NULL);
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
TCHAR szBuffer[10];
DWORD dwTimmer=0;
WaitForSingleObject(hSemaphore, INFINITE);
while(dwTimmer<100)
{
Sleep(100);
memset(szBuffer,0,10);
GetWindowText(hEdit2,szBuffer,10);
sscanf( szBuffer, "%d", &dwTimmer );
dwTimmer++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwTimmer);
SetWindowText(hEdit2,szBuffer);
}
ReleaseSemaphore(hSemaphore, 1, NULL);
return 0;
}
DWORD WINAPI ThreadProc3(LPVOID lpParameter)
{
TCHAR szBuffer[10];
DWORD dwTimmer=0;
WaitForSingleObject(hSemaphore, INFINITE);
while(dwTimmer<100)
{
Sleep(100);
memset(szBuffer,0,10);
GetWindowText(hEdit3,szBuffer,10);
sscanf( szBuffer, "%d", &dwTimmer );
dwTimmer++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwTimmer);
SetWindowText(hEdit3,szBuffer);
}
ReleaseSemaphore(hSemaphore, 1, NULL);
return 0;
}
DWORD WINAPI ThreadBegin(LPVOID lpParameter)
{
TCHAR szBuffer[10];
DWORD dwMoney=0;
hSemaphore = CreateSemaphore(NULL,0,3,NULL);
hThread[0] = ::CreateThread(NULL, 0, ThreadProc1,NULL, 0, NULL);
hThread[1] = ::CreateThread(NULL, 0, ThreadProc2,NULL, 0, NULL);
hThread[2] = ::CreateThread(NULL, 0, ThreadProc3,NULL, 0, NULL);
//開始準備紅包
while(dwMoney<1000)
{
memset(szBuffer,0,10);
GetWindowText(hEditSet,szBuffer,10);
sscanf( szBuffer, "%d", &dwMoney );
dwMoney++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwMoney);
SetWindowText(hEditSet,szBuffer);
}
ReleaseSemaphore(hSemaphore, 2, NULL);
::WaitForMultipleObjects(3, hThread,TRUE,INFINITE);
::CloseHandle(hSemaphore);
return 0;
}
BOOL CALLBACK MainDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
BOOL bRet = FALSE;
switch(uMsg)
{
case WM_CLOSE:
{
EndDialog(hDlg,0);
break;
}
case WM_INITDIALOG:
{
hEditSet = GetDlgItem(hDlg,IDC_EDIT_SET);
hEdit1 = GetDlgItem(hDlg,IDC_EDIT_1);
hEdit2 = GetDlgItem(hDlg,IDC_EDIT_2);
hEdit3 = GetDlgItem(hDlg,IDC_EDIT_3);
SetWindowText(hEditSet,"0");
SetWindowText(hEdit1,"0");
SetWindowText(hEdit2,"0");
SetWindowText(hEdit3,"0");
break;
}
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDC_BUTTON_BEGIN:
{
CreateThread(NULL, 0, ThreadBegin,NULL, 0, NULL);
return TRUE;
}
}
break ;
}
return bRet;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,MainDlgProc);
return 0;
}