您好,登錄后才能下訂單哦!
說明
OnIdle CPU空閑的情況下處理消息,如果需要定時功能,就需要使用定時器wxTimer
問題
比如定時器函數運行耗時10秒,定時的時間是10毫秒,是否是每隔10毫秒執行一次定時器函數,還是等待定時器函數運行結束,才開始重新計時
結果
在定時器函數中執行::Sleep(10000);等待10秒,發現實際上需要等待定時器函數執行結束,才開始重新計時。所以在如下的場景需要特別小心:需要定時讀取數據,而讀取數據之后,執行一大堆耗時的操作,這個時候,就需要啟動線程去處理,而不能在定時器函數中完成
例子
#include "wx/timer.h"
private:
wxTimer *m_timer;
//指定定時器的ID
#define TIMER_ID 1000
//將定時器ID和定時執行函數關聯起來
EVT_TIMER(TIMER_ID, CFlightInstrumentPanel::OnTimer)
//創建定時器,指定定時器ID使用哪個定時器
m_timer = new wxTimer(this, TIMER_ID);
//啟動定時器,參數是定時的時間間隔
m_timer->Start(1000);
編寫定時器的執行內容
void CFlightInstrumentPanel::OnTimer( wxTimerEvent& event )
{
static int x = 0;
if (x<1000)
{
wxClientDC dc(this);
wxPen pen(*wxRED,1);
dc.SetPen(pen);
dc.DrawRectangle(x, 0, 200, 300);
dc.SetPen(wxNullPen);
x=x+100;
}
}
停止定時器
m_timer->Stop();
注意
定時器是一種資源,類似文件句柄,不可能無限的創建,定時結束之后,最后停止定時器,釋放資源,并且如果在關閉窗口之前沒有停止定時器,會出現
0xC0000005: 讀取位置 0xFEEEFF06 時發生訪問沖突錯誤,相關的內容查看其它的文章
定時器SetTimer的效率分析場景分析
項目中使用wxWidgets框架,其中應用了該框架的定時器wxTimer,頻繁進行了開啟和關閉。在嵌入式操作系統中,性能是重中之重因此想嘗試分析當前這種應用場景,是否會消耗CPU和內存的資源,跟蹤wxWidgets的源碼,發現定時器在windows系統下調用了使用了SetTimer和KillTimer函數進行定時器的啟動和銷毀。
疑惑
第一點:啟動定時器是否是啟動一條線程,然后Sleep等待時間的觸發
第二點:頻繁啟動定時器,然后關閉,是否需消耗大量的資源
如果第一條成立的話,線程的創建以及切換都是非常
可觀的開銷
解惑
第一點:啟動定時器SetTimer不是啟動一個線程。該函數主要將新的
定時器結構加入內核的全局變量gptmrFirst這個鏈表,使用
KillTimer移除該定時器的結構體。系統會定時遍歷該鏈表,
一旦定時時間就緒,就會向程序發送WM_TIMER消息,應用程序
接收到消息,開始處理邏輯
第二點:啟動和關閉定時器也只是添加或者移除結構體,效率應該是
比較高的。創建線程的開銷以及占用的堆棧都是可觀的,盡管
可以設置線程堆棧的大小
前提
當前沒有搜索到windows定時器的源碼
參考:http://bbs.csdn.net/topics/360222963
基于以下的論斷:
win32k中有一個全局變量gptmrFirst,里面存放了第一個定時器結構的指針,定時器結構以鏈表的形式儲存
線程在消息循環中會調用GetMessageW->NtUserGetMessage->xxxInternalGetMessage->xxxRealInternalGetMessage
xxxRealInternalGetMessage后面會調用DoTimer,DoTimer就遍歷整個定時器鏈表,并比較每個Timer的Win32Thread指針是不是于win32k的
全局變量gptiCurrent,gptiCurrent中保存的是當前線程的Win32Thread結構的指針(許多win32k函數開頭都會有EnterCrit,這里面就設
置gptiCurrent為PsGetThreadWin32Thread的返回值)
如果是,表明這個Timer屬于當前線程,所以就檢查Timer是否已就緒(到時),如果就緒,則調用StoreQMessage放置一個WM_TIMER或
WM_SYSTIMER消息,后面xxxRealInternalGetMessage會將其取回
csrss.exe進程有一個叫raw input thread的內核線程,其內核對象地址的地址放在win32k全局變量gptiRit中
這個線程負責處理鍵盤輸入,鼠標輸入等,當然也有定時器,它會使用KeWaitForMultipleObjects等待一組內核對象,其中就有主定時
器,如果主定時器到時,就執行TimerProc
TimerProc函數會遍歷gptmrFirst鏈表,減少每個定時器的剩余時間,并把到期的定時器設置為已就緒
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。