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

注意:當WaitForMultipleObjects等待多個內核對象的時候,如果它的bWaitAll 參數設置為false。其返回值減去WAIT_OBJECT_0 就是參數lpHandles數組的序號。如果同時有多個內核對象被觸發,這個函數返回的只是其中序號最小的那個。

如果bWaitAll 為TRUE 則等待所有信號量有效在往下執行。(FALSE 當有其中一個信號量有效時就向下執行)

問題就在這里,我們如何可以獲取所有被同時觸發的內核對象。

舉個例子:我們需要在一個線程中處理從完成端口、數據庫、和可等待定時器來的數據。一個典型的實現方法就是:用WaitForMultipleObjects等待所有的這些事件。如果完成端口,數據庫發過來的數據量非常大,可等待定時器時間也只有幾十毫秒。那么這些事件同時觸發的幾率可以說非常大,我們不希望丟棄任何一個被觸發的事件。那么如何能高效地實現這一處理呢?   

MSDN中有一句非常重要的描述,它可以說是WaitForMultipleObjects用法的精髓:The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. When bWaitAll is FALSE, and multiple objects are in the signaled state, the function chooses one of the objects to satisfy the wait; the states of the objects not selected are unaffected.   

多個內核對象被觸發時,WaitForMultipleObjects選擇其中序號最小的返回。而WaitForMultipleObjects它只會改變使它返回的那個內核對象的狀態。

這兒又會產生一個問題,如果序號最小的那個對象頻繁被觸發,那么序號比它大的內核對象將得不到被處理的機會。為了解決這一問題,可以采用雙WaitForMultipleObjects檢測機制來實現。見下面的例子:

DWORD WINAPI ThreadProc(LPVOID lpParameter)   
{   DWORD dwRet = 0;   int nIndex = 0;   while(1)   { dwRet = WaitForMultipleObjects(nCount,pHandles,false,INFINITE);   switch(dwRet)   {case WAIT_TIMEOUT:   break;   case WAIT_FAILED:   return 1;default:{nIndex = dwRet - WAIT_OBJECT_0;   ProcessHanlde(nIndex++);   //同時檢測其他的事件   while(nIndex < nCount) //nCount事件對象總數   {   dwRet = WaitForMultipleObjects(nCount - nIndex,&pHandles[nIndex],false,0);   switch(dwRet)   {case WAIT_TIMEOUT:   nIndex = nCount; //退出檢測,因為沒有被觸發的對象了.   break;case WAIT_FAILED:   return 1;   default:{nIndex = dwRet - WAIT_OBJECT_0;   ProcessHanlde(nIndex++);   }break;}//switch結束}//while結束}//default結束break;}//switch結束}//while結束return 0; 
}

SignalObjectAndWait()

你也可以同時通知一個內核對象,同時等待另一個內核對象,這兩個操作以原子的方式進行。
語法

DWORD SignalObjectAndWait(HANDLE hObjectToSignal,//通知的內核對象HANDLE hObjectToWaitOn,//等待的內核對象DWORD  dwMilliseconds,//等待的時間BOOL   bAlertable//與IO完成端口有關的參數,暫不討論
);

參數

  • hObjectToSignal
    要發信號的對象的句柄。此對象可以是信號量,互斥量或事件。
    如果句柄是信號量,則需要SEMAPHORE_MODIFY_STATE訪問權限。如果句柄是事件,則需要EVENT_MODIFY_STATE訪問權限。如果句柄是互斥鎖且調用者不擁有互斥鎖,則函數將失敗并顯示ERROR_NOT_OWNER。

  • hObjectToWaitOn
    要等待的對象的句柄。該SYNCHRONIZE訪問權是必需的; 有關更多信息,請參閱同步對象安全性和訪問權限 。有關可以指定其句柄的對象類型的列表,請參閱“備注”部分。

  • dwMilliseconds
    超時間隔,以毫秒為單位。即使對象的狀態是非信號且沒有完成或異步過程調用(APC)對象排隊,該函數也會在間隔過去時返回。如果dwMilliseconds為零,則該函數測試對象的狀態,檢查排隊的完成例程或APC,并立即返回。如果dwMilliseconds是INFINITE,則函數的超時間隔永遠不會過去。

  • bAlertable
    如果此參數為TRUE,則該函數在系統對I / O完成例程或APC函數進行排隊時返回,并且該線程調用該函數。如果為FALSE,則函數不返回,并且線程不調用完成例程或APC函數。
    當排隊APC的函數調用完成時,完成例程排隊。只有當bAlertable為TRUE且調用線程是排隊APC的線程時,此函數才會返回并調用完成例程。

返回值

返回代碼/值描述
WAIT_ABANDONED/0x00000080L指定的對象是在擁有線程終止之前由擁有互斥對象的線程未釋放的互斥對象。互斥對象的所有權被授予調用線程,并且互斥鎖被設置為無信號。如果互斥鎖正在保護持久狀態信息,則應檢查它是否一致。
WAIT_IO_COMPLETION/0x000000C0L等待由一個或多個排隊到線程的用戶模式 異步過程調用(APC)結束。
WAIT_OBJECT_0/0x00000000L發出指定對象的狀態信號。
WAIT_TIMEOUT/0x00000102L超時間隔已過,對象的狀態未發出信號。
WAIT_FAILED/(DWORD)0xFFFFFFFF該功能失敗了。要獲取擴展錯誤信息,請調用 GetLastError。

備注
所述SignalObjectAndWait功能提供了一個更有效的方式來信號發送一個對象,然后在另一等待相比單獨的函數調用諸如 SetEvent的隨后WaitForSingleObject的。

該 SignalObjectAndWait函數可以等待以下對象:

  • 更改通知
  • 控制臺輸入
  • 事件
  • 內存資源通知
  • 互斥
  • 處理
  • 信號

線程可以使用SignalObjectAndWait函數來確保工作線程在發信號通知對象之前處于等待狀態。例如,線程和工作線程可以使用句柄來事件對象來同步它們的工作。該線程執行如下代碼:

 dwRet = WaitForSingleObject(hEventWorkerDone, INFINITE);if( WAIT_OBJECT_0 == dwRet)SetEvent(hEventMoreWorkToDo);

工作線程執行如下代碼:

dwRet = SignalObjectAndWait(hEventWorkerDone,hEventMoreWorkToDo,INFINITE, FALSE);

注意,“信號”和“等待”不能保證作為原子操作執行。在調用SignalObjectAndWait的線程開始等待第二個對象之前,在其他處理器上執行的線程可以觀察第一個對象的信號狀態。

在Windows 7中使用SignalObjectAndWait 和PulseEvent時要格外小心 ,因為在多個線程之間使用這些API會導致應用程序死鎖。由信號發送線程SignalObjectAndWait 調用PulseEvent以發信號通知的等待對象SignalObjectAndWait呼叫。在某些情況下,SignalObjectAndWait的調用者無法及時接收等待對象的信號狀態,從而導致死鎖。

使用等待函數和直接或間接創建窗口的代碼時要小心。如果一個線程創建了任何窗口,它必須處理消息。消息廣播將發送到系統中的所有窗口。使用沒有超時間隔的等待函數的線程可能會導致系統死鎖。間接創建窗口的兩個代碼示例是DDE和COM CoInitialize。因此,如果您有一個創建窗口的線程,請務必從另一個線程調用SignalObjectAndWait。如果無法做到這一點,可以使用 MsgWaitForMultipleObjects或 MsgWaitForMultipleObjectsEx,但功能不相同。

要編譯使用此函數的應用程序,請將 _WIN32_WINNT 定義為0x0400或更高版本。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448255.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448255.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448255.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

設置 shell 腳本中 echo 顯示內容帶顏色

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 shell腳本中echo顯示內容帶顏色顯示,echo顯示帶顏色&#xff0c;需要使用參數 -e 格式如下&#xff1a; echo -e "\033[字背景顏…

Visual C++ 編譯器選項 /MD、/ML、/MT、/LD

前段時間編譯一個引用自己寫的靜態庫的程序時老是出現鏈接時的多個重定義的錯誤&#xff0c;而自己的代碼明明沒有重定義這些東西&#xff0c;譬如&#xff1a; LIBCMT.lib(_file.obj) : error LNK2005: ___initstdio already defined in libc.lib(_file.obj) LIBCMT.lib(_fi…

Delphi面向對象編程的20條規則

Delphi面向對象編程的20條規則 作者簡介 Marco Cantu是一個知名的Delphi專家&#xff0c;他曾出版過《精通Delphi》系列叢書&#xff0c;《Delphi開發手冊》以及電子書《精通Pascal》(該電子書可在網上免費獲得)。他講授的課題是Delphi基礎和高級開發技巧。你可以通過他…

制動失靈怎么辦?

定義 制動過程中&#xff0c;由于制動器某些零部件的損壞或發生故障&#xff0c;使運動部件(或運動機械)不能保持停止狀態或不能按要求停止運動的現象。 制動失靈的原因 制動失靈的關鍵在于制動系統無法對汽車施加足夠的制動力&#xff0c;包括制動液管路液位不足或進入空氣、制…

OpenDDS用idl生成自定義數據類型時遇到的一個問題

問題&#xff1a;這里會提示LNK2005重復定義的錯誤 解決方案&#xff1a; 解決后&#xff1a;

解決:Connect to xx.xx.xxx.xx :8081 [/xx.xx.xx.xx] failed: Connection refu sed: connect -> [H

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 自行啟動了個 Nenux 服務。想把本地工程推送到 個人私服&#xff0c;執行命令&#xff1a;mvn deploy 報錯&#xff1a; Failed to…

ADOQuery 查詢 刪除 修改 插入

//利用combobox組件查詢數據庫表procedure TForm1.Button1Click(Sender: TObject);beginADOQuery1.Close;ADOQuery1.SQL.Clear;ADOQuery1.SQL.Add(select * from trim(ComboBox2.Text));ADOQuery1.Active:true;end&#xff1b; //查詢記錄procedure TForm1.Button1Click(Sender…

防爆胎,有妙招

對于大多數人來說&#xff0c;買車難,養車更難。許多人擁有了新車&#xff0c;卻沒有足夠的知識去好好保養汽車&#xff0c;這實在是非常可惜。如何做好汽車的保養工作,讓我們的愛車更好的為我們工作&#xff1f;夏天熾熱的天氣&#xff0c;是否讓你為爆胎煩惱不已&#xff1f;…

Qt之QProcess(一)運行cmd命令

Qt提供了QProcess類&#xff0c;QProcess可用于完畢啟動外部程序&#xff0c;并與之交互通信。 一、啟動外部程序的兩種方式&#xff1a; &#xff08;1&#xff09;一體式&#xff1a;void QProcess::start(const QString & program, const QStringList & arguments…

Docker 方式安裝 Nexus 私服

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 從Docker 官方倉庫查找鏡像&#xff1a; docker search nexus 2. 拉取鏡像&#xff1a; docker pull 你選中的鏡像的名字  pull…

shader飛線改進版

項目github地址&#xff1a;https://github.com/ecojust/flyline 前面寫過一個飛線(基于THREE.Line進行的顏色變化)&#xff0c;只是簡單地將可視區片元顏色的alpha通道值設為1.0&#xff0c;不在可視區的設為0.0。效果是這樣的&#xff1a; 做得很粗糙&#xff0c;而且因為線是…

轉向盤失控怎么辦?

定義 轉向失控就是方向盤不管用了&#xff0c;打方向盤&#xff0c;但是前輪不動&#xff0c;不受方向盤控制。 轉向失控的原因 轉向失控可能因為車輛過快、酒駕、疲勞、車況不佳、雨雪路滑等&#xff0c;還有轉向機構中有零部件脫落、損壞、卡滯時&#xff0c;也會使轉向機構突…

Socket網絡編程【獲取本機IP】

//12.3.2//運行環境VS2013//獲取本地IP #include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib")void main() { // 調用WSAStarup初始化WINsock庫 WSADATA wsaData; ::WSAStartup( MAKEWORD(2,2), &wsaData);// 存放主機名的…

onresize

1 window.onresize function (ev) { 2 console.log(尺寸發生改變&#xff01;); 3 }; 4 5 window.addEventListener(resize, function (ev) { 6 console.log(尺寸發生改變&#xff01;); 7 }); 1 /*2 當屏幕的寬度>960時&#xff0c;頁面的背景顏色為紅色…

Vuejs:組件 slot 內容分發

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 本文是在官方文檔的基礎上&#xff0c;更加細致的說明&#xff0c;代碼更多更全。 簡單來說&#xff0c;更適合新手閱讀 &#xff08;…

C++獲取本機所有ip地址,可區分類型是有線無線虛擬機還是回環

一個小程序&#xff0c;可以獲取本地所有ip地址&#xff0c;包括有線&#xff0c;無線&#xff0c;虛擬機&#xff0c;環回接口網卡&#xff0c;等。 如圖&#xff0c;一臺機器多個網卡&#xff1a; 程序執行結果&#xff1a; #include"stdio.h" #include"…

頓悟人生十一句話

一、永遠不要埋怨你已經發生的事情 如果你打算忍受一件事情就閉上嘴巴吧。要么就改變它&#xff0c;要么就安靜的接受它。 二、最讓你忿忿不平的問題&#xff0c;就是你需要解決的問題 一個被酒后駕駛的司機撞死自己兒子的婦女&#xff0c;發起了反對酒后駕駛母親協會…

Mybatis 在 IDEA 中使用 generator 逆向工程生成 pojo,mapper

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 使用mybatis可以逆向生成pojo和mapper文件有很多種方式&#xff0c;我以前用的是mybtais自帶的generator包來生成&#xff0c;連接如下&…

控制臺程序隱藏方法總結(四種)

學習計算機&#xff0c;往往先從Windows環境下學習編程&#xff0c;學習編程&#xff0c;往往從C學起&#xff0c;學習C&#xff0c;往往又從控制臺程序學習&#xff0c;何為控制臺&#xff0c;就是那個黑框白字的界面。對于這樣一個最初認為奇陋無比而現在認為無所不能的編程平…

十大教養,讓你氣度非凡!

01.守時 無論是開會、赴約&#xff0c;有教養的人從不遲到。他們懂得&#xff0c;即使是無意遲到&#xff0c;對其他準時到場的人來說&#xff0c;也是不尊重的表現。 02.談吐有節 注意從不隨便打斷別人的談話&#xff0c;總是先聽完對方的發言&#xff0c;然后再去反駁或者補…