WaitForSingleObject 的用法

1.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 有返回直才執行後面的代碼。在這裏舉個例子:

先創建一個全局 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 執行一次,當設置事件爲有信號狀態時,線程就執行完畢了。

2. WaitForSingleObject
當指定的對象處於有信號狀態或者等待時間結束的狀態時,此函數返回。
DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD dwMilliseconds
);
參數:
hHandle:指定對象或事件的句柄;
dwMilliseconds: 等待時間,以毫妙爲單位,當超過等待時間時,此函數將返回。如果該參數設置爲0,則該函數立即返回,如果設置爲INFINITE,則該函數直到有信號才返回。
返回值:
如果此函數成功,該函數的返回之標識了引起該函數返回的事件。返回值如下:
  WAIT_ABANDONED(0x00000080L)
  指定的對象是一個互斥對象,該對象沒有被擁有該對象的線程在線程結束前釋放。互斥對象的所有權被同意授予調用該函數的線程。互斥對象被設置成爲無信號狀態。
  WAIT_OBJECT_0 (0x00000000L)
  指定的對象出有有信號狀態。
  WAIT_TIMEOUT (0x00000102L)
  超過等待時間,指定的對象處於無信號狀態
如果失敗,返回 WAIT_FAILED;
備註:
此函數檢查指定的對象或事件的狀態,如果該對象處於無信號狀態,則調用線程處於等待狀態,此時該線程不消耗CPU時間,
該函數可以等待如下對象:
  Change notification 
  Console input 
  Event 
  Job 
  Memory resource notification 
  Mutex 
  Process 
  Semaphore 
  Thread 
  Waitable timer 
需求:
Client Requires Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows Me, Windows 98, or Windows 95. 
Server Requires Windows Server 2003, Windows 2000 Server, or Windows NT Server. 
Header Declared in Winbase.h; include Windows.h.   
Library Link to Kernel32.lib.    
DLL Requires Kernel32.dll.  

程序舉例:
1、創建對話框應用程序,項目名稱爲MyTestThread
2、添加按鈕,命名爲啓動和停止,在對話框中增加編輯框,ID爲IDC_TIME,
3、增加成員變量,HANDLE m_hThread[2],此爲線程的句柄;
4、定義全局變量,用來控制線程的運行與否;
   volatile BOOL m_ThreadRun[2];
5、增加全局事件對象,用來監控線程,控制線程是否運行。
   CEvent event;
   注意:4、5定義的對象,必須在.cpp文件中定義;
6、聲明回調函數。回調函數必須是全局函數或靜態函數。聲明方式如下:
void ThreadFunc1(LPVOID pParam);
void ThreadFunc2(LPVOID pParam);
   回調函數的實現如下:
void ThreadFunc1(LPVOID pParam)
{
  CTime time;
  CString strTime;
  event.ResetEvent();
  m_ThreadRun[0] = true;
  m_ThreadRun[1] = true;
  DWORD ThreadID = ::GetCurrentThreadId();
  while(m_ThreadRun[0])
  {
   time = CTime::GetCurrentTime();
   strTime = time.Format("%H:%M:%S");
   CMyTestThreadDlg* pDlg = (CMyTestThreadDlg*)pParam;
   pDlg->SetDlgItemText(IDC_TIME,strTime);
   Sleep(1000);
  } 
}

void ThreadFunc2(LPVOID pParam)
{
  
  CTime time;
  CString strTime;
  DWORD ThreadID = ::GetCurrentThreadId();

//event爲有信號狀態,則下邊的函數執行後,該線程則開始運行,如果event爲無信號狀態,則下邊的函數執行

//後,該線程處於等待狀態,直到有信號纔開始運行;
  ::WaitForSingleObject(event,INFINITE);
  while(m_ThreadRun[1])
  {
   time = CTime::GetCurrentTime();
   strTime = time.Format("%H:%M:%S");
   CMyTestThreadDlg* pDlg = (CMyTestThreadDlg*)pParam;
   pDlg->SetDlgItemText(IDC_TIME,"OK");
   Sleep(1000);
   ::WaitForSingleObject(event,INFINITE);
  } 
}

7、定義保存線程ID的成員變量:DWORD m_ThreadID[2];
8、對啓動和停止按鈕增加消息響應函數,如下:
void CMyTestThreadDlg::OnBnClickedOk()
{
  // TODO: 在此添加控件通知處理程序代碼
  m_hThread[0] = ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc1,this,0,&m_ThreadID[0]);
  m_hThread[1] = ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc2,this,0,&m_ThreadID[1]);


  GetDlgItem(IDC_BUTTON1)->EnableWindow(false);
  GetDlgItem(IDC_BUTTON2)->EnableWindow(true);
}

void CMyTestThreadDlg::OnBnClickedCancel()
{
  m_ThreadRun[0] = false;
  event.SetEvent();
  GetDlgItem(IDC_BUTTON1)->EnableWindow(true);
  GetDlgItem(IDC_BUTTON2)->EnableWindow(false);
}

編譯運行,設置斷點,可以查看運行情況。

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