Delphi定时器控件TTimer“一睡不醒”问题研究
1,试验1—基础代码
1.1页面控件与代码
|
定时器 |
Timer1 |
Timer_work |
|
Interval |
1000 |
1500 |
|
Enabled |
True |
True |
|
Ontimer事件 |
if Timer1.Tag= then exit; //tag=1表示正在忙
Timer1.Tag := ;
try
memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' + intToStr(Timer_work.tag));
finally
Timer1.Tag := ;
end;
|
if Timer_work.Tag= then exit; //tag=1表示正在忙
Timer_work.Tag := ;
try
memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' + intToStr(Timer1.tag));
finally
Timer_work.Tag := ;
end;
|
1.2运行结果与分析
39:15Timer_work.tag=0 39:16Timer1.tag=0 39:16Timer_work.tag=0 39:17Timer1.tag=0 39:17Timer_work.tag=0 39:19Timer_work.tag=0 39:19Timer1.tag=0 39:20Timer_work.tag=0 39:20Timer1.tag=0 39:21Timer_work.tag=0 39:22Timer_work.tag=0 39:22Timer1.tag=0 39:23Timer_work.tag=0 39:24Timer1.tag=0 39:24Timer_work.tag=0 39:25Timer_work.tag=0 39:25Timer1.tag=0 39:26Timer_work.tag=0 39:27Timer1.tag=0 39:27Timer_work.tag=0 39:28Timer_work.tag=0 39:28Timer1.tag=0 39:29Timer_work.tag=0 39:30Timer1.tag=0 39:30Timer_work.tag=0 39:31Timer_work.tag=0 39:31Timer1.tag=0 39:32Timer_work.tag=0 39:33Timer1.tag=0 39:33Timer_work.tag=0
以上为运行一段时间后memo1中的结果。其中:
Timer_work.tag=0出现的次数为17次
Timer1.tag=0出现的次数为12次
17/12约等于18/12=3:2=1.5:1
结果分析如下:
1,各个定时器均处于主线程中,可能是串行工作机制。即在Timer1的OnTimer事件中,Timer_work的OnTimer事件已经执行完毕,反之亦然,不会2个定时器事件同时处于执行状态。
2,2个定时器事件的执行次数比与定时器周期基本成反比。符合预期。
2,试验2—加入sleep和ProcessMessages后出现故障
2.1页面控件与代码
|
定时器 |
Timer1 |
Timer_work |
|
Interval |
1000 |
1500 |
|
Enabled |
True |
True |
|
Ontimer事件 |
if Timer1.Tag= then exit; //tag=1表示正在忙
Timer1.Tag := ;
try
application.ProcessMessages;
sleep(); memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' + intToStr(Timer_work.tag));
finally
Timer1.Tag := ;
end;
|
if Timer_work.Tag= then exit; //tag=1表示正在忙
Timer_work.Tag := ;
try
application.ProcessMessages;
sleep(); memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' + intToStr(Timer1.tag));
finally
Timer_work.Tag := ;
end;
|
2.2运行结果与分析
02:33Timer_work.tag=0 02:34Timer1.tag=0 02:35Timer_work.tag=0 02:36Timer_work.tag=1 02:37Timer_work.tag=1 02:38Timer_work.tag=1 02:39Timer_work.tag=1 02:40Timer_work.tag=1 02:41Timer_work.tag=1 02:42Timer_work.tag=1 02:43Timer_work.tag=1 02:44Timer_work.tag=1 02:45Timer_work.tag=1 02:46Timer_work.tag=1 02:47Timer_work.tag=1 02:48Timer_work.tag=1 02:49Timer_work.tag=1 02:50Timer_work.tag=1 02:51Timer_work.tag=1 02:52Timer_work.tag=1 02:53Timer_work.tag=1 02:54Timer_work.tag=1 02:55Timer_work.tag=1 02:56Timer_work.tag=1 02:57Timer_work.tag=1 02:58Timer_work.tag=1 02:59Timer_work.tag=1 03:00Timer_work.tag=1 03:01Timer_work.tag=1
以上为运行一段时间后memo1中的结果。其中:
在Timer1的OnTimer事件中,出现了Timer_work.tag=1。这说明2个定时器事件同时处于执行状态。
以上事件出现后,就一直维持每一秒输出一次Timer_work.tag=1,说明程序一直在执行Timer1的OnTimer事件,而Timer_work的OnTimer事件被抑制。
结果分析如下:
1,各个定时器均处于主线程中,可能是串行工作机制。但并不意味着“在Timer1的OnTimer事件中,Timer_work的OnTimer事件已经执行完毕”,可能从一个定时器事件中跳出去执行另一个计时器事件,也就是说2个定时器事件可能同时处于事件响应过程中,但同一时间只有1个事件正在执行。
2,本身只准备睡眠1秒的Timer_work.,经过了25秒仍未恢复执行。而timer1调用周期为1秒加上sleep 1秒,应该是每2秒输出1次“Timer_work.tag=1”,但实际输出间隔是1秒,不符合预期。
3,试验3—故障分析
3.1页面控件与代码
|
定时器 |
Timer1 |
Timer_work |
|
Interval |
1000 |
1500 |
|
Enabled |
True |
True |
|
Ontimer事件 |
if Timer1.Tag= then exit; //tag=1表示正在忙
Timer1.Tag := ;
try
application.ProcessMessages;
memo1.Lines.Add(formatDatetime('NN:SS',now)+' in Timer1Timer before sleep' );
sleep(); memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' + intToStr(Timer_work.tag));
finally
Timer1.Tag := ;
memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' + intToStr(Timer1.tag));
end;
|
if Timer_work.Tag= then exit; //tag=1表示正在忙
Timer_work.Tag := ;
try
application.ProcessMessages;
sleep();
|
停止按钮的响应事件:
procedure TForm1.Button1Click(Sender: TObject);
begin
memo1.Lines.Add(formatDatetime('NN:SS',now)+' 停止按钮已按下..' );
Timer_work.Enabled := False;
Timer1.Enabled := False;
memo1.Lines.Add(formatDatetime('NN:SS',now)+' 计时器已停止.' );
end;
3.2运行结果与分析
48:19 in Timer1Timer before sleep 48:20Timer_work.tag=1 48:20Timer1.tag=0 48:20 in Timer1Timer before sleep 48:21Timer_work.tag=1 48:21Timer1.tag=0 48:21 in Timer1Timer before sleep 48:22Timer_work.tag=1 48:22Timer1.tag=0 48:22 in Timer1Timer before sleep 48:23Timer_work.tag=1 48:23Timer1.tag=0 48:23 in Timer1Timer before sleep 48:24Timer_work.tag=1 48:24Timer1.tag=0 48:24 in Timer1Timer before sleep 48:25Timer_work.tag=1 48:25Timer1.tag=0 48:25 in Timer1Timer before sleep 48:26Timer_work.tag=1 48:26Timer1.tag=0 48:26 in Timer1Timer before sleep 48:27Timer_work.tag=1 48:27Timer1.tag=0 48:27 in Timer1Timer before sleep 48:28Timer_work.tag=1 48:28Timer1.tag=0 48:28 in Timer1Timer before sleep 48:29Timer_work.tag=1 48:29Timer1.tag=0 48:29 in Timer1Timer before sleep 48:30Timer_work.tag=1 48:30Timer1.tag=0 48:30 停止按钮已按下.. 48:30 计时器已停止. 48:31Timer1.tag=0 48:31Timer_work.tag=0
以上为运行一段时间后memo1中的结果。其中:
在Timer1的OnTimer事件中,sleep前后相差1秒,说明时间主要被sleep函数消耗,而不是被timer的周期消耗。
Timer_work.tag=0一直到停止该计时器时才出现。
结果分析如下:
1,timer控件的周期只是调用执行的时间间隔,实际执行时间需考虑多种因素。假设timer周期为T1,timer事件响应函数执行时间为T2,那么实际执行周期为max(T1,T2),而不是T1+T2。
2,多计时器同时启用时,可能出现无法想象的结果。应避免使用application.ProcessMessages和sleep的同时调用。
4,实验总结
实验证明,以下情景可能出现问题:
- 多个计时器函数中,至少有2个函数调用了application.ProcessMessages和 sleep中的1个或2个。
结论:
- 为避免计时器“一睡不醒”,在计时器函数中应该谨慎调用sleep函数。
Delphi定时器控件TTimer“一睡不醒”问题研究的更多相关文章
- <总结>delphi WebBrowser控件的使用中出现的bug
Delphi WebBrowser控件的使用中出现的bug: 1.WebBrowser.Visible=false:Visible属性不能使WebBrowser控件不可见,暂时用 WebBrowse ...
- 修改Delphi工具控件的默认字体
修改Delphi工具控件的默认字体: 注册表: Delphi 6: HKEY_CURRENT_USER\Software\Borland\Delphi\6.0Delphi 7: HKEY_ ...
- Delphi WebBrowser控件的使用(大全 good)
Delphi WebBrowser控件的使用 WebBrowser控件属性:1.Application 如果该对象有效,则返回掌管WebBrowser控件的应用程序实现的自动化对象(IDis ...
- Delphi TcxtreeList控件说明 转
Delphi TcxtreeList控件说明 树.cxTreeList 属性: Align:布局,靠左,靠右,居中等 AlignWithMargins:带边框的布局 Anchors:停靠 (akT ...
- delphi按钮控件的default属性
delphi按钮控件的default属性用于设置默认命令按钮,.设置为true时,按[Enter键]相当于用鼠标单击了该按钮 .窗口中如果有多个按钮的default是true的话,就根据tabinde ...
- Delphi fmx控件在手机滑动与单击的问题
Delphi fmx控件在手机滑动与单击的问题 (2016-03-08 10:52:00) 转载▼ 标签: it delphi 分类: Delphi10 众所周知,fmx制作的app,对于象TEdit ...
- Delphi maskedit控件的掩码含义及用法方法
Delphi maskedit控件的掩码含义及用法方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 2 ...
- Delphi StringGrid控件的用法
Delphi StringGrid控件 组件名称:StringGrid ●固定行及固定列: StringGrid.FixedCols:=固定行之数; StringGrid.Fixe ...
- Delphi IDHTTP控件:GET/POST 请求
Delphi IDHTTP控件:GET/POST 请求 最近一直在使用IDHTTP,下面是一些关于 GET.POST 请求基本使用方法的代码 一.GET 请求 1 procedure GetDem ...
随机推荐
- uptime命令
uptime命令能够打印系统总共运行了多长时间和系统的平均负载.uptime命令可以显示的信息显示依次为:现在时间.系统已经运行了多长时间.目前有多少登陆用户.系统在过去的1分钟.5分钟和15分钟内的 ...
- windows server2012之部署HTTPS安全站点
现在的互联网越来越重视网络安全方面的内容,像我们日常生活中浏览的网上银行网站等涉及安全的你都会发现有https 的标志出现,在URL前加https://前缀表明是用SSL加密的. 你的电脑与服务器之间 ...
- Burpsuite实验(二)
一.这次我们使用一下burpsuite的代理拦截功能. 图中的proxy是代理的选项,其中intercept是拦截的功能,在浏览器中请求的包,都经过它. 这是打开拦截时候的状态.forward是通过此 ...
- 【NOIP2014】 联合权值
[题目链接] 点击打开链接 [算法] 如果(u,v)的距离为2,那么有两种可能 : 1.u和v为祖孙关系 2.u和v为兄弟关系 树形DP即可,详见代码 [代码] #include<bits/st ...
- JAVA 集合JGL
集合 Java提供了四种类型的“集合类”:Vector(矢量).BitSet(位集).Stack(堆栈)以及Hashtable(散列表).与拥有集合功能的其他语言相比,尽管这儿的数量显得相当少,但仍然 ...
- word-break: break-all word-break:keep-all word-wrap: break-word三者的区别
word-break属性:指定非CJK脚本的断行规则. 值 描述 normal 使用浏览器默认的换行规则. break-all 允许在单词内换行. keep-all 只能在半角空格或连字符处换行. w ...
- JDK8 Lamdba表达式转换成Map,value为null问题
// 将list转换成Map类型 Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getI ...
- JDK由浅到深的理解
一.JDK的安装 二.JDK安装后目录下的文件夹的用处 bin:编译器(javac.exe); db:jdk从1.6之后内置Derby数据库,它是一个纯用Java实现的内存数据库,Apache的开源项 ...
- SpringSercurity基础
创建 spring 配置文件 spring-security.xml intercept-url 表示拦截页面 /* 表示的是该目录下的资源,只包括本级目录不包括下级目录 /** 表示的是该目 ...
- $.ajax从后台取数据 然后做字符串拼接的例子