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();    
memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' + intToStr(Timer1.tag)); finally Timer_work.Tag := ; memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' + intToStr(Timer_work.tag)); end;

停止按钮的响应事件:

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“一睡不醒”问题研究的更多相关文章

  1. <总结>delphi WebBrowser控件的使用中出现的bug

    Delphi WebBrowser控件的使用中出现的bug:  1.WebBrowser.Visible=false:Visible属性不能使WebBrowser控件不可见,暂时用 WebBrowse ...

  2. 修改Delphi工具控件的默认字体

    修改Delphi工具控件的默认字体: 注册表: Delphi 6:    HKEY_CURRENT_USER\Software\Borland\Delphi\6.0Delphi 7:    HKEY_ ...

  3. Delphi WebBrowser控件的使用(大全 good)

    Delphi WebBrowser控件的使用 WebBrowser控件属性:1.Application      如果该对象有效,则返回掌管WebBrowser控件的应用程序实现的自动化对象(IDis ...

  4. Delphi TcxtreeList控件说明 转

    Delphi TcxtreeList控件说明   树.cxTreeList 属性: Align:布局,靠左,靠右,居中等 AlignWithMargins:带边框的布局 Anchors:停靠 (akT ...

  5. delphi按钮控件的default属性

    delphi按钮控件的default属性用于设置默认命令按钮,.设置为true时,按[Enter键]相当于用鼠标单击了该按钮 .窗口中如果有多个按钮的default是true的话,就根据tabinde ...

  6. Delphi fmx控件在手机滑动与单击的问题

    Delphi fmx控件在手机滑动与单击的问题 (2016-03-08 10:52:00) 转载▼ 标签: it delphi 分类: Delphi10 众所周知,fmx制作的app,对于象TEdit ...

  7. 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 ...

  8. Delphi StringGrid控件的用法

    Delphi StringGrid控件 组件名称:StringGrid         ●固定行及固定列:  StringGrid.FixedCols:=固定行之数;  StringGrid.Fixe ...

  9. Delphi IDHTTP控件:GET/POST 请求

    Delphi IDHTTP控件:GET/POST 请求   最近一直在使用IDHTTP,下面是一些关于 GET.POST 请求基本使用方法的代码 一.GET 请求 1 procedure GetDem ...

随机推荐

  1. 原:maven+springMVC+mybatis+junit详细搭建过程

    阅读目录 1.  工程目录结构整理清楚 2.  引入依赖包 3. 配置数据库连接属性 4.  配置spring配置文件 5.  java代码编写(model,dao,service层代码) 6.  m ...

  2. UVA-11054(扫描法)

    题意: n个等距村庄,每个村庄要么买酒要么卖酒,把k个单位的酒运到相邻村庄去需要k个单位的劳动力,问最少需要多少劳动力才能满足所有的村庄的要求; 思路: 上次做了一个环的,这个是直线的,就是一个大水题 ...

  3. Codeforces Round #419 (Div. 1) 补题 CF 815 A-E

    A-C传送门 D Karen and Cards 技巧性很强的一道二分优化题 题意很简单 给定n个三元组,和三个维度的上限,问存在多少三元组,使得对于给定的n个三元组中的每一个,必有两个维度严格小于. ...

  4. CS231n 2016 通关 第二章-KNN 作业分析

    KNN作业要求: 1.掌握KNN算法原理 2.实现具体K值的KNN算法 3.实现对K值的交叉验证 1.KNN原理见上一小节 2.实现KNN 过程分两步: 1.计算测试集与训练集的距离 2.通过比较la ...

  5. WebService安全解决方案—简单握手协议

    具体方案如下图: 2.解决方案分析 A.SiteA每次向SiteB发送的请求参数都不一样,造成伪造者难以模仿和推敲里面的算法过程. B.伪造者获得了SayHelloRequest的数据,它向SiteB ...

  6. 6-6 Haar特征3

    B区域是包含AB这样两部分的.C区域是包含A和C这样两部分的.B区域和C区域它描述的是一个横条和一个竖条.D区域是四个方块之和. #haar 1 什么是haar? 特征 = 像素 运算 ->结果 ...

  7. (水题)Codeforces - 327C - Magic Five

    https://codeforces.com/problemset/problem/327/C 因为答案可以有前导零,所以0和5一视同仁.每个小节内,以排在第 $i$ 个的5为结尾的序列即为在前面 $ ...

  8. 51nod1174【基于线段树的RMQ】

    很基础啊~ #include <bits/stdc++.h> using namespace std; typedef long long LL; const int INF=-0x3f3 ...

  9. bzoj 3676: [Apio2014]回文串【回文自动机】

    回文自动机板子 或者是SAM+manacher+倍增,就是manacher求本质不同回文串(让f++的串),然后在SAM倍增查询对应点出现次数 #include<iostream> #in ...

  10. [USACO10FEB]购买巧克力Chocolate Buying 【假背包真贪心】 By cellur925

    题目传送门 继续dp刷题计划,看到这道题,第一眼感觉不就是显然的完全背包嘛.把背包打完要开始填充数组大小的时候成为了mengbier,发现数据极大,达到了1e18.显然这不是一道平凡的背包题目. 于是 ...