新聞中心
但它的缺陷就在這里。

你怎么知道,你所認為的正在等待事件的線程就一定是”真的(正在等待)”?顯然我們不能使用如下的方法:
因為在上面的代碼中,激發(fā)信號和等待事件這兩個操作存在一個競爭條件。信號對象所激發(fā)的線程可能在你等待事件對象之前,就已經(jīng)完成了所有工作并將激發(fā)出一個事件脈沖(PulseEvent)了。
你可以嘗試使用SignalObjectAndWait這個函數(shù),它會將信號激發(fā)和等待合并到一個單獨的操作中。但是即使是這樣,你還是無法確定線程在脈沖發(fā)生時是否正在等待事件。
當(dāng)一個線程等待事件時,設(shè)備驅(qū)動或者內(nèi)核本身的一部分可能會借用線程來進行一些任務(wù)處理(通過內(nèi)核模式APC)。在此期間,線程不處于等待狀態(tài),因為設(shè)備驅(qū)動正在使用它。如果PulseEvent在線程借用時發(fā)生,則它不會從等待中喚醒,因為PulseEvent函數(shù)只會喚醒在PulseEvent發(fā)生時正在等待的線程。
用戶模式程序不僅無法阻止內(nèi)核模式代碼對用戶模式程序線程執(zhí)行此操作,甚至也沒辦法檢測它是否已經(jīng)發(fā)生。
(你可能會看到這種事情發(fā)生的一個地方是,如果你將調(diào)試器附加到進程,因為調(diào)試器會執(zhí)行諸如掛起和恢復(fù)線程之類的事情,這會導(dǎo)致內(nèi)核 APC。)
因此,PulseEvent 函數(shù)是沒有什么用的,我們應(yīng)該避免使用它。
它繼續(xù)存在只是為了向后兼容。
附加信息:與內(nèi)核 APC 相關(guān)的整個業(yè)務(wù)還意味著,當(dāng)你激發(fā)一個信號量、自動重置事件或其他在發(fā)出信號時釋放單個線程的同步對象時,你無法預(yù)測哪個線程將被喚醒。 如果一個線程被“借用”來服務(wù)內(nèi)核 APC,那么當(dāng)它返回到等待列表時,它“回到行尾”。 因此,等待內(nèi)核對象的對象的順序是不可預(yù)測的并且不能依賴。
總結(jié)
請老老實實使用SetEvent/ResetEvent,簡單,實在!
最后
Raymond Chen的《The Old New Thing》是我非常喜歡的博客之一,里面有很多關(guān)于Windows的小知識,對于廣大Windows平臺開發(fā)者來說,確實十分有幫助。
本文來自:《PulseEvent is fundamentally flawed》
網(wǎng)站名稱:談?wù)凱ulseEvent的缺陷,你明白了嗎?
當(dāng)前地址:http://m.5511xx.com/article/ccchcce.html


咨詢
建站咨詢
