VC事件,事件響應API,CEvent類

WaitForSingleObject的用法

  WaitForSingleObject的用法

  DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );

  參數hHandle是一個事件的句柄,第二個參數dwMilliseconds是時間間隔。如果時間是有信號狀態返回WAIT_OBJECT_0,如果時間超過dwMilliseconds值但時間事件還是無信號狀態則返回WAIT_TIMEOUT。

  hHandle可以是下列對象的句柄:


  Change notification

  Console input

  Event

  Job

  Memory resource notification

  Mutex

  Process

  Semaphore

  Thread

  Waitable timer

  WaitForSingleObject函數用來檢測hHandle事件的信號狀態,當函數的執行時間超過dwMilliseconds就返回,但如果參數dwMilliseconds爲INFINITE時函數將直到相應時間事件變成有信號狀態才返回,否則就一直等待下去,直到WaitForSingleObject有返回值才執行後面的代碼。此外,當dwMilliseconds設置爲特殊值0時,測試hHandle核心對象是否被激發,函數立即返回。

  返回值:

  WAIT_ABANDONED:當hHandle爲mutex時,如果擁有mutex的線程在結束時沒有釋放核心對象會引發此返回值。


  WAIT_OBJECT_0:核心對象已被激活


  WAIT_TIMEOUT:等待超時


  WAIT_FAILED:出現錯誤,可通過GetLastError得到錯誤代碼


  在這裏舉個例子:

  先創建一個全局Event對象g_event:

  CEvent g_event;

  在程序中可以通過調用CEvent::SetEvent設置事件爲有信號狀態。

  下面是一個線程函數MyThreadPro()

  UINT CFlushDlg::MyThreadProc( LPVOID pParam )

  {

      WaitForSingleObject(g_event,INFINITE);

      For(;;)

      {

        ………….

      }

      return 0;

  }

  在這個線程函數中只有設置g_event爲有信號狀態時才執行下面的for循環,因爲g_event是全局變量,所以我們可以在別的線程中通過g_event. SetEvent控制這個線程。

  還有一種用法就是我們可以通過WaitForSingleObject函數來間隔的執行一個線程函數的函數體

  UINT CFlushDlg::MyThreadProc( LPVOID pParam )

  {

      while(WaitForSingleObject(g_event,MT_INTERVAL)!=WAIT_OBJECT_0)

      {

        ………………

      }

      return 0;

  }

  在這個線程函數中可以可以通過設置MT_INTERVAL來控制這個線程的函數體多久執行一次,當事件爲無信號狀態時函數體隔MT_INTERVAL執行一次,當設置事件爲有信號狀態時,線程就執行完畢了。

 

 

 

 

setevent
  CEvent::SetEvent
  BOOL SetEvent();
  返回值:如果操作成功,則返回非零值,否則爲0。
  說明:
  設置事件的狀態爲有標記,釋放任意等待線程。如果事件是手工的,此事件將保持有標記直到調用ResetEvent。這種情況下將釋放多個線程,如果事件是自動的,此事件將保持有標記,直到一個線程被釋放,系統將設置事件的狀態爲無標記。如果沒有線程在等待,則此事件將保持有標記,直到一個線程被釋放。
 
(轉載)
CEvent類
CEvent 類提供了對事件的支持。事件是一個允許一個線程在某種情況發生時,喚醒另外一個線程的同步對象。事件告訴線程何時去執行某一給定的任務,從而使多個線程流平滑。例如在某些網絡應用程序中,一個線程(記爲A)負責監聽通信端口,另一個線程(記爲B)負責更新用戶數據。通過使用CEvent類,線程A可以通知線程B何時更新用戶數據,這樣線程B可以儘快地更新用戶數據。每一個CEvent對象可以有兩種狀態:有信號狀態(signaled)和無信號狀態(nonsignaled)。線程監視位於其中的CEvent類對象的狀態,並在相應的時候採取相應的操作。
     在MFC中,CEvent類對象有兩種類型,分別是所謂的人工事件和自動事件。對於自動事件,當其獲得信號後,就會釋放下一個可用的線程。一個自動 CEvent對象在被至少一個線程釋放後會自動返回到無信號狀態;而人工事件對象獲得信號後,釋放所有可利用線程,直到調用成員函數ReSetEvent ()將其設置爲無信號狀態時爲止。注意,在創建CEvent類的對象時,默認創建的是自動事件。

CEvent的各成員函數的原型與參數說明如下。
CEvent(BOOL bInitiallyOwn = FALSE,
BOOL bManualReset = FALSE,
LPCTSTR lpszName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );


bInitiallyOwn:若bInitiallyOwn爲TRUE,則使CMultilock類對象和CSingleLock類對象的線程可用;否則,要訪問資源的線程必須等待。該參數的默認值爲FALSE。
bManualReset:指定要創建的CEvent對象是屬於手工事件還是自動事件。爲TRUE,則爲手工事件,否則爲自動事件。該參數默認值爲FALSE。
lpszName:指定要創建的事件對象的名,如果該事件對象將跨進程使用,則此參數不能爲NULL。如果該參數和一個已經存在的CEvent對象相同,則該構造函數返回一個對這個已存在對象的引用;如果參數和一個已存在的非CEvent類的同步對象(如CMutex)相同,則對象創建失敗;
lpsaAttribute:指向SECURITY_ATTRIBUTES結構的指針,該參數決定要創建的事件對象的安全屬性,一般置爲NULL。
在事件對象建成後,可以調用其成員函數來改變其狀態。
BOOL CEvent::SetEvent ();


將CEvent類對象的狀態設置爲有信號狀態,並且釋放所有等待的線 程;如果該事件是人工事件,則CEvent類對象保持爲有信號狀態,直到調用成員函數ResetEvent()將其重新設爲無信號狀態時爲止,這樣該事件 就可以釋放多個線程;如果CEvent類對象爲自動事件,則在SetEvent()將事件設置爲有信號狀態後,CEvent類對象由系統自動重置爲無信號 狀態,除非一個線程被釋放。
如果該函數執行成功,則返回非零值,否則返回零。
BOOL CEvent::ResetEvent();


該函數將事件的狀態設置爲無信號狀態,並保持該狀態直至SetEvent()被調用時爲止。由於自動事件是由系統自動重置,故自動事件不需要調用該函數。
如果該函數執行成功,返回非零值,否則返回非零。
BOOL CEvent::PulseEvent()


發送一個事件脈衝,該函數完成一系列操作後才返回。對於自動事件,PulseEvent()將事件設置爲有信號狀態,等待一個線程被釋放,將事件重置爲無信號狀態,然後PulseEvent()返回;對於人工事件,則將等待該事件的所有線程被釋放,事件被自動重置爲無信號狀態,然後PulseEvent()返回。
一個CEvent對象在線程中被創建後,自動處於無信號狀態,但在另一個線程中可以調用Win32 API WaitForSingleObject()函數來監視其狀態。
該函數的原型及參數說明如下:
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

其中hHandle爲指向要監視的同步對象的句柄,dwMilliseconds爲監視hHandle所指向的對象所設置的超時值,單位爲毫秒。當在線程的執行函數中調用該函數時,線程暫時掛起,系統監視hHandle所指向的對象的狀態。
如果經過dwMilliseconds毫秒後,hHandle指向的對象變爲有信號狀態,則WaitForSingleObject()返回,線程被釋放,且返回值爲WAIT_TIMEOUT;
如果在掛起的dwMilliseconds毫秒內,線程所等待的對象在某一時刻變爲有信號,則該函數立即返回,返回值爲WAIT_OBJECT_0。
參數dwMilliseconds有兩個具有特殊意義的值:0和INFINITE。若爲0,則該函數立即返回;若爲INFINITE,則線程一直被掛起,直到hHandle所指向的對象變爲有信號狀態時爲止。如果CEvent對象爲自動事件,則當WaitForSingleObject(hHandle,INFINITE)返回時,自動把CEvent對象重置爲無信號狀態。CEvent::SetEvent()把對象設置爲有信號狀態,釋放等待的線程。CEvent::ResetEvent()把對象設置爲無信號狀態,程序在WaitForSingleObject(hHandle,INFINITE)處等待。
例程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’”按鈕,體會事件對象的作用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章