將 CEvent 類物件的狀態設定為有訊號狀態。如果事件是人工事件,則 CEvent 類物件保持為有訊號狀態,直到呼叫成員函式ResetEvent
()將
其重新設為無訊號狀態時為止。如果CEvent 類物件為自動事件,則在SetEvent()將事件設定為有訊號狀態後,CEvent
類物件由系統自動重置為無訊號狀態。
步驟/方法
如果該函式執行成功,則返回非零值,否則返回零。 3、BOOL CEvent::ResetEvent();
該函式將事件的狀態設定為無訊號狀態,並保持該狀態直至SetEvent()被呼叫時為止。由於自動事件是由系統自動重置,故自動事件不需
要呼叫該函式。如果該函式執行成功,返回非零值,否則返回零。我們一般通過呼叫WaitForSingleObject函式來監視事件狀態。前面我們已經
介紹了該函式。由於語言描述的原因,CEvent
類的理解確實有些難度,但您只要通過仔細回味下面例程,多看幾遍就可理解。
例程9 MultiThread9
建立一個基於對話方塊的工程MultiThread9,在對話方塊IDD_MULTITHREAD9_DIALOG中加入一個按鈕和兩個編輯框控制元件,按鈕的ID為IDC_WRITEW,標
題為“寫‘W’”;兩個編輯框的ID分別為IDC_W和IDC_D,屬性都選中Read-only;
在MultiThread9Dlg.h檔案中宣告兩個執行緒函式: UINT WriteW(LPVOID pParam);
UINT WriteD(LPVOID pParam);
使用ClassWizard分別給IDC_W和IDC_D新增CEdit類變數m_ctrlW和m_ctrlD;
在MultiThread9Dlg.cpp檔案中新增如下內容:
為了檔案中能夠正確使用同步類,在檔案開頭新增
#include "afxmt.h"
定義事件物件和一個字元陣列,為了能夠在不同執行緒間使用,定義為全域性變數。 CEvent eventWriteD;
char g_Array[10];
新增執行緒函式: UINT WriteW(LPVOID pParam)
{
CEdit *pEdit=(CEdit*)pParam;
pEdit->SetWindowText("");
for(int i=0;i<10;i++)
{
g_Array[i]=''W'';
pEdit->SetWindowText(g_Array);
Sleep(1000);
}
eventWriteD.SetEvent();
return 0;
}
UINT WriteD(LPVOID pParam)
{
CEdit *pEdit=(CEdit*)pParam;
pEdit->SetWindowText("");
WaitForSingleObject(eventWriteD.m_hObject,INFINITE);
for(int i=0;i<10;i++)
{
g_Array[i]=''D'';
pEdit->SetWindowText(g_Array);
Sleep(1000);
}
return 0;
}
仔細分析這兩個執行緒函式, 您就會正確理解CEvent 類。執行緒WriteD執行到
WaitForSingleObject(eventWriteD.m_hObject,INFINITE);處等待,直到事件eventWriteD為有訊號該執行緒才往下執行,因為eventWriteD物件
是自動事件,則當WaitForSingleObject()返回時,系統自動把eventWriteD物件重置為無訊號狀態。
雙擊按鈕IDC_WRITEW,新增其響應函式: void CMultiThread9Dlg::OnWritew()
{
CWinThread *pWriteW=AfxBeginThread(WriteW,
&m_ctrlW,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pWriteW->ResumeThread();
CWinThread *pWriteD=AfxBeginThread(WriteD,
&m_ctrlD,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pWriteD->ResumeThread();
}
編譯並執行程式,單擊“寫‘W’”按鈕,體會事件物件的作用。
C、使用CMutex 類
互斥物件與臨界區物件很像.互斥物件與臨界區物件的不同在於:互斥物件可以在程序間使用,而臨界區物件只能在同一程序的各執行緒間使用
。當然,互斥物件也可以用於同一程序的各個執行緒間,但是在這種情況下,使用臨界區會更節省系統資源,更有效率。
D、使用CSemaphore 類
當需要一個計數器來限制可以使用某個執行緒的數目時,可以使用“訊號量”物件。CSemaphore
類的物件儲存了對當前訪問某一指定資源的執行緒的計數值,該計數值是當前還可以使用該資源的執行緒的數目。如果這個計數達到了零,則所有
對這個CSemaphore
類物件所控制的資源的訪問嘗試都被放入到一個佇列中等待,直到超時或計數值不為零時為止。一個執行緒被釋放已訪問了被保護的資源時,計
數值減1;一個執行緒完成了對被控共享資源的訪問時,計數值增1。這個被CSemaphore
類物件所控制的資源可以同時接受訪問的最大執行緒數在該物件的構建函式中指定。
CSemaphore 類的建構函式原型及引數說明如下:
CSemaphore (LONG lInitialCount=1,
LONG lMaxCount=1,
LPCTSTR pstrName=NULL,
LPSECURITY_ATTRIBUTES lpsaAttributes=NULL);
lInitialCount:訊號量物件的初始計數值,即可訪問執行緒數目的初始值;
lMaxCount:訊號量物件計數值的最大值,該引數決定了同一時刻可訪問由訊號量保護的資源的執行緒最大數目;
後兩個引數在同一程序中使用一般為NULL,不作過多討論;
在用CSemaphore
類的建構函式建立訊號量物件時要同時指出允許的最大資源計數和當前可用資源計數。一般是將當前可用資源計數設定為最大資源計數,每增
加一個執行緒對共享資源的訪問,當前可用資源計數就會減1,只要當前可用資源計數是大於0的,就可以發出訊號量訊號。但是當前可用計數減
小到0時,則說明當前佔用資源的執行緒數已經達到了所允許的最大數目,不能再允許其它執行緒的進入,此時的訊號量訊號將無法發出。執行緒在處
理完共享資源後,應在離開的同時通過ReleaseSemaphore()函式將當前可用資源數加1。
下面給出一個簡單例項來說明 CSemaphore 類的用法。
例程10 MultiThread10
建立一個基於對話方塊的工程MultiThread10,在對話方塊IDD_MULTITHREAD10_DIALOG中加入一個按鈕和三個編輯框控制元件,按鈕的ID為IDC_START,
標題為“同時寫‘A’、‘B’、‘C’”;三個編輯框的ID分別為IDC_A、IDC_B和IDC_C,屬性都選中Read-only;
在MultiThread10Dlg.h檔案中宣告兩個執行緒函式: UINT WriteA(LPVOID pParam);
UINT WriteB(LPVOID pParam);
UINT WriteC(LPVOID pParam);
使用ClassWizard分別給IDC_A、IDC_B和IDC_C新增CEdit類變數m_ctrlA、m_ctrlB和m_ctrlC;
在MultiThread10Dlg.cpp檔案中新增如下內容:
為了檔案中能夠正確使用同步類,在檔案開頭新增:
#include "afxmt.h"
定義訊號量物件和一個字元陣列,為了能夠在不同執行緒間使用,定義為全域性變數:CSemaphore semaphoreWrite(2,2);
//資源最多訪問執行緒2個,當前可訪問執行緒數2個
char g_Array[10];
新增三個執行緒函式:
UINT WriteA(LPVOID pParam)
{
CEdit *pEdit=(CEdit*)pParam;
pEdit->SetWindowText("");
WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
CString str;
for(int i=0;i<10;i++)
{
pEdit->GetWindowText(str);
g_Array[i]=''A'';
str=str+g_Array[i];
pEdit->SetWindowText(str);
Sleep(1000);
}
ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
return 0;
}
UINT WriteB(LPVOID pParam)
{
CEdit *pEdit=(CEdit*)pParam;
pEdit->SetWindowText("");
WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
CString str;
for(int i=0;i<10;i++)
{
pEdit->GetWindowText(str);
g_Array[i]=''B'';
str=str+g_Array[i];
pEdit->SetWindowText(str);
Sleep(1000);
}
ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
return 0;
}
UINT WriteC(LPVOID pParam)
{
CEdit *pEdit=(CEdit*)pParam;
pEdit->SetWindowText("");
WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
for(int i=0;i<10;i++)
{
g_Array[i]=''C'';
pEdit->SetWindowText(g_Array);
Sleep(1000);
}
ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
return 0;
}
這三個執行緒函式不再多說。在訊號量物件有訊號的狀態下,執行緒執行到WaitForSingleObject語句處繼續執行,同時可用執行緒數減1;若執行緒執
行到WaitForSingleObject語句時訊號量物件無訊號,執行緒就在這裡等待,直到訊號量物件有訊號執行緒才往下執行。
雙擊按鈕IDC_START,新增其響應函式: void CMultiThread10Dlg::OnStart()
{
CWinThread *pWriteA=AfxBeginThread(WriteA,
&m_ctrlA,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pWriteA->ResumeThread();
CWinThread *pWriteB=AfxBeginThread(WriteB,
&m_ctrlB,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pWriteB->ResumeThread();
CWinThread *pWriteC=AfxBeginThread(WriteC,
&m_ctrlC,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pWriteC->ResumeThread();
}
好吧,多執行緒程式設計就介紹到這裡,希望本文能對您有所幫助。