国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Windows中定時器Timer使用中的注意事項

2019-11-09 21:17:58
字體:
供稿:網(wǎng)友

在任何語言任何操作系統(tǒng)下的開發(fā)中,定時器都是一個必不可少的功能,大部分的操作系統(tǒng)和語言都有內(nèi)置的定時器接口可供調(diào)用。在windows API中有一組定時器相關(guān)函數(shù),包括CreateTimerQueue、DeleteTimerQueue、CreateTimerQueueTimer、DeleteTimerQueueTimer,可以很方便的實現(xiàn)定時器相關(guān)功能。

CreateTimerQueue,創(chuàng)建定時器隊列;

DeleteTimerQueue,銷毀定時器隊列;

DeleteTimerQueueEx,銷毀定時器隊列,與上一個函數(shù)的區(qū)別在于,這個函數(shù)的第二個參數(shù)可以指定是否等待當(dāng)前隊列中的回調(diào)函數(shù)執(zhí)行完再返回;

CreateTimerQueueTimer,創(chuàng)建定時器;

DeleteTimerQueueTimer,銷毀定時器;

具體函數(shù)定義可參見MSDN。

最近在使用這組定時器函數(shù)的過程中遇過一個問題,某個線程在調(diào)用DeleteTimerQueueTimer函數(shù)時block住了,無法正常返回。仔細(xì)閱讀MSDN上關(guān)于這個函數(shù)的說明:

Syntax

C++
BOOL WINAPI DeleteTimerQueueTimer(  _In_opt_ HANDLE TimerQueue,  _In_     HANDLE Timer,  _In_opt_ HANDLE CompletionEvent);

Parameters

TimerQueue [in, optional]

A handle to the timer queue. This handle is returned by the CreateTimerQueue function.

If the timer was created using the default timer queue, this parameter should be NULL.

Timer [in]

A handle to the timer-queue timer. This handle is returned by the CreateTimerQueueTimer function.

CompletionEvent [in, optional]

A handle to the event object to be signaled when the system has canceled the timer and all callback functions have completed. This parameter can be NULL.

If this parameter is INVALID_HANDLE_VALUE, the function waits for any running timer callback functions to complete before returning.

If this parameter is NULL, the function marks the timer for deletion and returns immediately. If the timer has already expired, the timer callback function will run to completion. However, there is no notification sent when the timer callback function has completed. Most callers should not use this option, and should wait for running timer callback functions to complete so they can perform any needed cleanup.

在我的代碼中最后一個參數(shù)賦值為INVALID_HANDLE_VALUE而非NULL,也就說會等待任何該定時器的回調(diào)函數(shù)執(zhí)行完再返回。從程序的執(zhí)行l(wèi)og來看,在跑到DeleteTimerQueueTimer這個函數(shù)后,定時器的回調(diào)函數(shù)仍然被調(diào)用了很多次,DeleteTimerQueueTimer并沒有在某個回調(diào)函數(shù)執(zhí)行完后就正常返回。

由于不知道windows這幾個定時器函數(shù)具體如何實現(xiàn)的(如果有哪位高人了解,萬望知悉),只能根據(jù)現(xiàn)有現(xiàn)象猜測個大概。

假設(shè)某個Timer的執(zhí)行間隔是1s,那么每隔1s,系統(tǒng)會將它的回調(diào)函數(shù)放到Timer線程的執(zhí)行隊列中(CreateTimerQueueTimer的最后一個參數(shù)可以指定是否在Timer當(dāng)前線程執(zhí)行回調(diào)函數(shù)),如果當(dāng)前Timer隊列為空,即前面的回調(diào)函數(shù)都已執(zhí)行完畢,那么新加入的回調(diào)函數(shù)就能夠立即得到執(zhí)行,這樣這個Timer就處于一個健康狀態(tài),每個回調(diào)函數(shù)都能在指定時間執(zhí)行,并在指定時間間隔內(nèi)返回。

假設(shè)一種異常情況,某個Timer的執(zhí)行間隔為1s,但是它的回調(diào)函數(shù)會執(zhí)行2s,那么除了第一次執(zhí)行,后面的每次調(diào)用,都會比原定時間更晚,第二次調(diào)用在2s后,晚了1s,第三次調(diào)用在4s后,晚了2s,依次類推。如果DeleteTimerQueueTimer這個函數(shù)的實現(xiàn)也是把銷毀定時器這個動作放到了Timer線程隊列中,那么Timer的回調(diào)函數(shù)執(zhí)行了n次,DeleteTimerQueueTimer的執(zhí)行就會被相應(yīng)的推遲n-1s,在n足夠大時,DeleteTimerQueueTimer就會表現(xiàn)為block住,無法返回,不過最終還是能返回的,并不是死循環(huán)。

為了印證這種想法,我寫了個很簡單的程序:

VOID CALLBACK TimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ){ Sleep(100 * 1000); }int main(){ HANDLE timer_queue = CreateTimerQueue(); HANDLE timer; CreateTimerQueueTimer(&timer, timer_queue, TimerCallback, NULL, 0, 10, WT_EXECUTEINTIMERTHREAD); Sleep(100*1000); DeleteTimerQueueEx(timer_queue, INVALID_HANDLE_VALUE); return 0;}

代碼中定時器執(zhí)行間隔10ms,回調(diào)函數(shù)會執(zhí)行100s,然后在開始運行100s后銷毀定時器。然后F5運行,然后......從中午等到半夜12點還是沒返回,就卡在了DeleteTimerQueueEx,這里我很想放個哭瞎的表情,然而好像并不能放動圖。按照我所猜測的定時器實現(xiàn)原理,我算了一下,當(dāng)前這個函數(shù)要等27天半左右才能執(zhí)行完。。。真是等到天荒地老。

之后稍微了改了下執(zhí)行參數(shù),定時器執(zhí)行100ms,運行10s后調(diào)用DeleteTimerQueueEx,果然等待時間大大縮短,1分鐘左右就返回了。

從上面這個實驗來看,windows這一組定時器函數(shù)的實現(xiàn)原理應(yīng)該就和我想的差不多。那么了解了原理之后,改問題就好改多了。要避免銷毀定時器時block住,主要有兩個方面需要考慮:

1. 避免回調(diào)函數(shù)的執(zhí)行時間超過調(diào)用間隔;

2. 避免將所有定時器創(chuàng)建在一個線程中。CreateTimerQueue時,系統(tǒng)會創(chuàng)建一個Timer線程,后面調(diào)用CreateTimerQueueTimer時,最后一個參數(shù)指定為WT_EXECUTEINTIMERTHREAD時,系統(tǒng)會將該新創(chuàng)建的Timer的回調(diào)函數(shù)放到默認(rèn)的Timer線程隊列中。也可以將最后一個參數(shù)指定為WT_EXECUTELONGFUNCTION,由系統(tǒng)判斷是否為該定時器的創(chuàng)建新線程,如果定時器的回調(diào)函數(shù)會執(zhí)行比較久,那么最好使用這個參數(shù),否則會影響其他定時器的正常運行。

以上就是本人最近使用windows定時器的一些總結(jié),歡迎各路大拿拍磚(隱隱的還是感覺很多有問題的地方)。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 西华县| 三门县| 高青县| 博白县| 淮阳县| 沁源县| 海盐县| 恭城| 开鲁县| 通河县| 贵阳市| 荣昌县| 丰原市| 玛多县| 博湖县| 瑞丽市| 通山县| 陵水| 谢通门县| 湘西| 阜新市| 梁平县| 武定县| 石台县| 仁寿县| 玛沁县| 正安县| 伊川县| 惠安县| 东乡县| 婺源县| 温泉县| 湘潭县| 吉林省| 平塘县| 新乐市| 招远市| 同江市| 体育| 伊通| 蒙自县|