日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

事件EVENT,WaitForSingleObject(),WaitForMultipleObjecct()和SignalObjectAndWait() 的使用(上)

發(fā)布時間:2023/12/19 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 事件EVENT,WaitForSingleObject(),WaitForMultipleObjecct()和SignalObjectAndWait() 的使用(上) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

用戶模式的線程同步機制效率高,如果需要考慮線程同步問題,應該首先考慮用戶模式的線程同步方法。但是,用戶模式的線程同步有限制,對于多個進程之間的線程同步,用戶模式的線程同步方法無能為力。這時,只能考慮使用內核模式。

Windows提供了許多內核對象來實現(xiàn)線程的同步。對于線程同步而言,這些內核對象有兩個非常重要的狀態(tài):“已通知”狀態(tài),“未通知”狀態(tài)(也有翻譯為:受信狀態(tài),未受信狀態(tài))。Windows提供了幾種內核對象可以處于已通知狀態(tài)和未通知狀態(tài):進程、線程、作業(yè)、文件、控制臺輸入/輸出/錯誤流、事件、等待定時器、信號量、互斥對象。


與事件EVENT的配合使用,能夠解決很多同步問題,也可以在數(shù)據(jù)達到某個狀態(tài)時啟動另一個線程的執(zhí)行,如報警。

EVENT 的幾個函數(shù):

1、CreateEvent和OpenEvent

HANDLE WINAPI CreateEvent(__in LPSECURITY_ATTRIBUTES lpEventAttributes, //表示安全控制,一般直接傳入NULL,表示不能被子進程繼承__in BOOL bManualReset, //參數(shù)確定事件是手動置位還是自動置位,傳入TRUE表示手動置位,傳入FALSE表示自動置位。__in BOOL bInitialState, //Event的初始狀態(tài), TRUE為觸發(fā),FALSE未觸發(fā)__in LPCTSTR lpName //Event object的名字,NULL表示沒名字(without a name) ); 要是CreateEvent創(chuàng)建的事件沒名字 這個函數(shù)就沒啥用了,不多做介紹,可查看msn。 HANDLE WINAPI OpenEvent( //獲得已經存在的Event的事件句柄__in DWORD dwDesiredAccess,__in BOOL bInheritHandle,__in LPCTSTR lpName //要打開的事件名字 );

2、SetEvent,觸發(fā)事件

BOOL SetEvent(HANDLE hEvent);

3、ResetEvent,使事件狀態(tài)設為未觸發(fā),如在創(chuàng)建事件時第二個參數(shù)為TRUE手動設置,則需要該函數(shù)去恢復事件為未觸發(fā)狀態(tài)。

BOOL SetEvent(HANDLE hEvent);

4、PulseEvent, 如在創(chuàng)建事件時第二個參數(shù)為TRUE手動設置,其功能相當于SetEvent()后立即調用ResetEvent(),最好別用

BOOL PulseEvent(HANDLE hEvent)

5、CloseHandle(),關閉該句柄。

事件是內核對象,事件分為手動置位事件和自動置位事件。事件Event內部它包含一個使用計數(shù)(所有內核對象都有),一個布爾值表示是手動置位事件還是自動置位事件,另一個布爾值用來表示事件有無觸發(fā)。事件可以由SetEvent()來觸發(fā),由ResetEvent()來設成未觸發(fā)。還可以由PulseEvent()來發(fā)出一個事件脈沖。


WaitForSingleObject()

在多線程下面,有時候我們會希望等待某一線程完成了再繼續(xù)做其他事情,要實現(xiàn)這個目的,可以使用Windows API函數(shù)WaitForSingleObject,或者WaitForMultipleObjects。這兩個函數(shù)都會等待Object被標為有信號(signaled)時才返回的。
那么,什么是信號呢?
簡單來說,Windows下創(chuàng)建的Object都會被賦予一個狀態(tài)量。如果Object被激活了,或者正在使用,那么該Object就是無信號,也就是不可用;另一方面,如果Object可用了,那么它就恢復有信號了。

這兩個函數(shù)的優(yōu)點是它們在等待的過程中會進入一個非常高效沉睡狀態(tài),只占用極少的CPU時間片。(這兩個函數(shù)都是在內核狀態(tài)下等待內核對象,不切換到用戶模式下,因而效率很高)

1、格式

DWORD WaitForSingleObject( HANDLE hHandle, DWORDdwMilliseconds);

有兩個參數(shù),分別是THandle和Timeout(毫秒單位)。

如果想要等待一條線程,那么你需要指定線程的Handle,以及相應的Timeout時間。當然,如果你想無限等待下去,Timeout參數(shù)可以指定系統(tǒng)常量INFINITE。

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

2. 使用對象
它可以等待如下幾種類型的對象:

Event(事件),Mutex(互斥量),Semaphore(信號量),Process(進程),Thread(線程),Change notification(變更通知),Console input(控制臺輸入),Job(可以被理解為進程的容器),Memory resource notification(內存資源通知),Waitable timer(等待定時器)

3. 返回類型
WAIT_ABANDONED:當hHandle為mutex時,如果擁有mutex的線程在結束時沒有釋放核心對象會引發(fā)此返回值。

WAIT_OBJECT_0:核心對象已被激活WAIT_TIMEOUT:等待超時WAIT_FAILED:出現(xiàn)錯誤,可通過GetLastError得到錯誤代碼

4.示例:

#include <windows.h> #include <stdio.h> #include <iostream.h> //聲明函數(shù) 創(chuàng)建線程 DWORD WINAPI FunProc( LPVOID lpParameter); void main() { HANDLE hThread; hThread=CreateThread(NULL,0,FunProc,NULL,0,NULL); DWORD dwRet=WaitForSingleObject(hThread, 1); if(dwRet==WAIT_OBJECT_0) { printf("創(chuàng)建的線程執(zhí)行結束\n"); } if(dwRet==WAIT_TIMEOUT) { printf("等待超時\n"); } if(dwRet==WAIT_ABANDONED) { printf("Abandoned\n"); } CloseHandle(hThread); } DWORD WINAPI FunProc( LPVOID lpParameter ) { int i=1; for(; i<1000; i++) { printf("%d ", i); if(! (i%10)) printf("\n"); } return 0; }

注意:不可以在WaitForSingleObject()之前執(zhí)行CloseHandle()否則會導致程序出錯!!
官方文檔解釋:

如果在wait操作仍處于暫掛狀態(tài)時關閉此句柄,則函數(shù)的行為將不明確。


WaitForMultipleObjecct()

WaitForMultipleObjects是Windows中的一個功能非常強大的函數(shù),幾乎可以等待Windows中的所有的內核對象

函數(shù)原型為:

DWORD WaitForMultipleObjects( DWORD nCount, // number of handles in the handle array CONST HANDLE *lpHandles, // pointer to the object-handle array BOOL fWaitAll, // wait flag DWORD dwMilliseconds // time-out interval in milliseconds );

參數(shù)解析:

  • DWORD 就是 Double Word, 每個word為2個字節(jié)的長度,DWORD雙字即為4個字節(jié),每個字節(jié)是8位。
  • nCount 指定列表中的句柄數(shù)量 最大值為MAXIMUM_WAIT_OBJECTS(64)

  • *lpHandles 句柄數(shù)組的指針。lpHandles為指定對象句柄組合中的第一個元素 HANDLE類型可以為(Event,Mutex,Process,Thread,Semaphore)數(shù)組

  • bWaitAll 等待的類型,如果為TRUE,表示除非對象都發(fā)出信號,否則就一直等待下去;如果FALSE,表示任何對象發(fā)出信號即可
  • dwMilliseconds指定要等候的毫秒數(shù)。如設為零,表示立即返回。如指定常數(shù)INFINITE,則可根據(jù)實際情況無限等待下去

函數(shù)的返回值有:

  • WAIT_ABANDONED_0:所有對象都發(fā)出消息,而且其中有一個或多個屬于互斥體(一旦擁有它們的進程中止,就會發(fā)出信號)
  • WAIT_TIMEOUT:對象保持未發(fā)信號的狀態(tài),但規(guī)定的等待超時時間已經超過
  • WAIT_OBJECT_0:所有對象都發(fā)出信號
  • WAIT_IO_COMPLETION:(僅適用于WaitForMultipleObjectsEx)由于一個I/O完成操作已作好準備執(zhí)行,所以造成了函數(shù)的返回
  • 返回WAIT_FAILED則表示函數(shù)執(zhí)行失敗,會設置GetLastError

如bWaitAll為FALSE,那么返回結果相似,只是可能還會返回相對于WAIT_ABANDONED_0或WAIT_OBJECT_0的一個正偏移量,指出哪個對象是被拋棄還是發(fā)出信號。

WAIT_OBJECT_0是微軟定義的一個宏,你就把它看成一個數(shù)字就可以了。

例如,WAIT_OBJECT_0 + 5的返回結果意味著列表中的第5個對象發(fā)出了信號

如果程序中的nObjectWait是WAIT_OBJECT_0 + 5

int nIndex = nObjectWait - WAIT_OBJECT_0;就是說nIndex =5也就表示第5個對象發(fā)出了信號

示例:
當 bWaitAll參數(shù)為FALSE可以等待其中之一的事件

HANDLE m_hEvent[2]; //兩事件 m_hEvent[0]=CreateEvent(NULL, FALSE, FALSE, NULL); m_hEvent[1]=CreateEvent(NULL, FALSE, FALSE, NULL); CreateThread(NULL, 0, MyThreadProc, this, 0, NULL); DWORD WINAPI MyThreadProc(LPVOID lpParam) { while(TRUE) { //每次等500毫秒 int nIndex = WaitForMultipleObjects(2, pThis->m_hEvent, FALSE,500); if (nIndex == WAIT_OBJECT_0 + 1) { //第二個事件發(fā)生 //ExitThread(0); //break; } else if (nIndex == WAIT_OBJECT_0) //第一個事件發(fā)生 { //第一個事件 } else if (nIndex == WAIT_TIMEOUT) //超時500毫秒 { //超時可作定時用 } } OutputDebugString("線程結束. /n"); return 0L;}

當要處理第一個事件時,你只需執(zhí)行SetEvent(m_hEvent[0]); 即可進入第一個事件的位置

當要執(zhí)行第二個事件時執(zhí)行SetEvent(m_hEvent[1]);

當 bWaitAll參數(shù)為TRUE等待所有的事件

DWORD WINAPI MyThreadProc(LPVOID lpParam) { while(TRUE) { //每次等500毫秒 int nIndex = WaitForMultipleObjects(2, pThis->m_hEvent, TRUE,500); if (WAIT_OBJECT_0 + 1<= nIndex <= WAIT_OBJECT_0) //所有事件發(fā)生 { //所有的信號量都有效時(事件都發(fā)生)其中之一無效。 }

總結

以上是生活随笔為你收集整理的事件EVENT,WaitForSingleObject(),WaitForMultipleObjecct()和SignalObjectAndWait() 的使用(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。