wxWidgets第十四课 wxTimer定时器

说明

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链表,减少每个定时器的剩余时间,并把到期的定时器设置为已就绪

时间: 2024-12-07 18:08:57

wxWidgets第十四课 wxTimer定时器的相关文章

wxWidgets第十六课 wxTimer没有调用stop导致崩溃的问题分析

场景 调用wxTimer定时器功能的时候,如果关闭当前的窗口,会出现上述的问题:0xC0000005: 读取位置 0xFEEEFF06 时发生访问冲突 说明 跟踪调用堆栈的具体情况,代码崩溃点指向IMPLEMENT_APP(CTestApp) 调用堆栈指向: wxEntry(int &,wchar_t * *) 未知 wxEntry(struct HINSTANCE__ *,struct HINSTANCE__ *,char *,int) 未知 > WinMain(HINSTANCE__ *

NeHe OpenGL教程 第四十四课:3D光晕

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第四十四课:3D光晕 3D 光晕 当镜头对准太阳的时候就会出现这种效果,模拟它非常的简单,一点数学和纹理贴图就够了.好好看看吧. 大家好,欢迎来到新的一课,在这一课中我们将扩展glCamera类,来实现镜头光晕的效果.在日常生活中,

NeHe OpenGL教程 第十四课:图形字体

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第十四课:图形字体 图形字体: 在一课我们将教你绘制3D的图形字体,它们可像一般的3D模型一样被变换. 这节课继续上一节课课的内容.在第13课我们学习了如何使用位图字体,这节课,我们将学习如何使用轮廓字体. 创建轮廓字体的方法类似于

Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗、嗅探、dns欺骗、session劫持

Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗.嗅探.dns欺骗.session劫持 文/玄魂 目录 Kali Linux Web 渗透测试—第十四课-arp欺骗.嗅探.dns欺骗.session劫持      1 关于嗅探.arp欺骗.会话劫持.............................................................. 1 视频教程地址:http://edu.51cto.com/course/course_id-1887.h

第二十四课:能量和功率

1.RC电路充电过程的能量特性: 电源提供的能量  Vs i 在T内积分 如果T远远大于时间常数,则该能量等于 CVs2 但是电容储存的能量等于 (1/2) CVs2 因此一半能量被电阻消耗,另一半则被电容储存起来 2.RC电路放电过程的能量特性: 所以能量消耗在电阻上 3.将两个过程相连,则电源消耗CVs2,一般在充电时消耗,一般在放电时消耗 因此平均功率等于 CVs2f   ,f是充放电的切换频率,愈大功率越大 4.类似于MODFET反相电路 两种功率之和:待机功率和动态功率,后者就是充放电

第三十四课 二维数组的存储 【项目1-3】

第三十四课 二维数组的存储 项目一[二维数组当函数参数] 定义一个函数来完成对参数数组中元素的求和工作,函数声明如下: [cpp] view plain copy print? int sum(int array[ ][4],int m,int n);  //该函数完成对array数组中的前m行和n列元素求和 在以下程序的基础上,完成对sum函数的定义. [cpp] view plain copy print? #include <stdio.h> int sum(int array[ ][4

OpenGL教程翻译 第十四课 相机控制(一)

OpenGL教程翻译 第十四课 相机控制(一) 原文地址:http://ogldev.atspace.co.uk/(源码请从原文主页下载) Background 在之前的教程中我们学习了如何在三维场景中的任何地方放置相机.那么我们下一步就应该学着去控制这个相机.相机可以向任何方向自由移动.我们可以用鼠标和键盘控制相机--鼠标控制视口方向,键盘控制我们的位置.这些都和第一人称视角相似.这一章我们主要来学习鼠标和键盘的控制. 我们仍然使用上下左右四个方向键.记住,我们的相机的变换取决于位置.targ

(二十四)linux新定时器:timefd及相关操作函数

timerfd是Linux为用户程序提供的一个定时器接口.这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景. 一,相关操作函数 #include <sys/timerfd.h> int timerfd_create(int clockid, int flags); int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itim

深入浅出CChart 每日一课——快乐高四第十四课 枝头红杏,Win32标准控件ChartCtrl之围城

本节课笨笨继续介绍ChartCtrl控件在DuiLib中的应用. 请大家先复习高四第三课. 本节课的方法和这一课的方法差不多,由于笨笨提供了ChartCtrl这个新工具,所以编程可以有一定的简化. 首先,XML文件和高四第三课完全一样. 其次,cpp文件只有CreateControl部分有所修改,如下.当然,前面那个CChartWnd变量不需要了. virtual CControlUI* CreateControl(LPCTSTR pstrClassName) { if (_tcsicmp(ps