2009-11-05 87 views
1

我試圖通過使用Windows計時器隊列來實現Windows GDI的高幀頻。相關的API是CreateTimerQueue, DeleteTimerQueueEx, CreateTimerQueueTimer,DeleteTimerQueueTimer定時器隊列,立即終止一個定時器?

定時器使用CreateTimerQueueTimer(&m_timer, m_timer_queue, TimerCallback, this, 0, 20, WT_EXECUTEINTIMERTHREAD);創建,以達到50fps的速度。 GDI操作(一些繪畫在Backstore中,加上InvalidateRect)不能是異步的,因此我不能選擇除WT_EXECUTEINTIMERTHREAD之外的其他標誌,因此繪圖代碼不需要額外的同步操作。我們的想法是在可能的情況下達到50fps,如果不是,只需以最大速度顯示每一幀。

在動畫結束時(達到總幀數),DeleteTimerQueueTimer被調用來銷燬計時器。

問題是DeleteTimerQueueTimer不會立即關閉回調函數的調用。當無法達到50fps的要求時,計時器將呼叫轉換爲隊列。在回調函數內調用DeleteTimerQueueTimer不會破壞隊列。結果,即使它決定關閉定時器,回調仍然被調用。

我該如何處理這個問題?

- 另一個說明,舊的timeSetEvent/timeKillEvent多媒體API似乎沒有這個問題。沒有隊列,當我調用timeKillEvent時,回調函數的調用立即停止。是否有可能實現與定時器隊列相同的行爲?

回答

2

您可以通過WT_EXECUTEONLYONCE標誌的CreateTimerQueueTimer功能。這將導致定時器只觸發一次而不是定期觸發。

然後您可以使用ChangeTimerQueueTimer方法重新安排計時器。

要覆蓋您的繪圖在框架中花費太長時間太久的時間,可以將一個CriticalSection添加到TimerHandler方法的開始處,這會導致第二個定時器等到第一個定時器完成。

1

如果你想以50fps +運行一些東西,你可能會做得更好,實際上只需要一個繪製循環來計算幀之間的時間量並相應地縮放動畫。定時器並不是真正意義上的開火。所以(這可能會在你的空閒處理程序中)。像,僞代碼(忽略缺少的錯誤處理):

static longlong last_frame; 
while(1) { 
    longlong current_frame = QueryPerformanceCounter(); 
    long delta = current_frame - last_frame; 

    // Do drawing here, scale amount to move by how much time has elapsed 

    last_frame = current_frame; 
} 
+0

謝謝,但多媒體計時器API怎麼沒有這個問題?什麼樣的間隔不是「太頻繁」? 「while(1)」加上「QueryPerformanceCounter」的成本遠高於多媒體定時器或定時器隊列定時器的成本?到目前爲止,我發現定時器隊列定時器幾乎不花費50fps的回調函數,而多媒體定時器僅花費一點CPU。 – 2009-11-06 03:15:02

0

DeleteTimerQueueTimer將取消定時器,前提是定時器尚未安排。 (當你使用WT_EXECUTEINTIMERTHREAD時,我相信它們是作爲一個APC從一個由定時器隊列和工作線程共享的線程池中排隊的)。如果它已經被調度(不只是運行) - 它將被運行並且DeleteTimerQueueTimer調用將阻止直到完成。

如果我正確理解您的問題,我可以提出以下建議嗎? 1.在調用DeleteTimerQueueTimer之前 - 設置一個標誌,說abortAllTimers爲true。 2.在每個定時器回調函數中檢查abortAllTimers是否爲真。如果它是真的 - 然後立即返回而不做任何繪圖。

最後 - 不應該從定時器回調中調用DeleteTimerQueueTimer。相反,我建議你應該從任何其他線程調用它 - 說你用來啓動定時器的線程。

希望這會有所幫助。

+0

從你的定時器回調函數中調用DeleteTimerQueueTimer是非常好的,只要你爲第三個參數傳遞NULL值,以便它是非阻塞的。 請參閱[鏈接](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682569(v = vs.85).aspx) – Derek 2012-05-07 16:05:09

+0

@Derek如果您傳遞NULL爲空第三參數。但是您不知道計時器何時完成,即何時可以安全地清除計時器回調所使用的資源。 – 2013-10-27 07:24:23