1,试验1—基础代码
1.1页面控件与代码
定时器app
Timer1函数
Timer_workspa
Interval线程
1000code
1500orm
Enabledblog
True事件
Trueci
Ontimer事件it
if Timer1.Tag=1 then exit; //tag=1表示正在忙
Timer1.Tag := 1;trymemo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' +intToStr(Timer_work.tag));finallyTimer1.Tag := 0;end;
if Timer_work.Tag=1 then exit; //tag=1表示正在忙
Timer_work.Tag := 1;trymemo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' +intToStr(Timer1.tag));finallyTimer_work.Tag := 0;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=1 then exit; //tag=1表示正在忙
Timer1.Tag := 1;tryapplication.ProcessMessages;
sleep(1000); memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' +intToStr(Timer_work.tag));finallyTimer1.Tag := 0;end;
if Timer_work.Tag=1 then exit; //tag=1表示正在忙
Timer_work.Tag := 1;tryapplication.ProcessMessages;
sleep(1000); memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' +intToStr(Timer1.tag));finallyTimer_work.Tag := 0;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=1 then exit; //tag=1表示正在忙
Timer1.Tag := 1;tryapplication.ProcessMessages;
memo1.Lines.Add(formatDatetime('NN:SS',now)+'in Timer1Timer before sleep');
sleep(1000); memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' +intToStr(Timer_work.tag));finallyTimer1.Tag := 0;
memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' +intToStr(Timer1.tag));end;
if Timer_work.Tag=1 then exit; //tag=1表示正在忙
Timer_work.Tag := 1;tryapplication.ProcessMessages;
sleep(1000);
memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' +intToStr(Timer1.tag));finallyTimer_work.Tag := 0;
memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' +intToStr(Timer_work.tag));end;
中止按钮的响应事件:
procedureTForm1.Button1Click(Sender: TObject);beginmemo1.Lines.Add(formatDatetime('NN:SS',now)+'中止按钮已按下..');
Timer_work.Enabled :=False;
Timer1.Enabled :=False;
memo1.Lines.Add(formatDatetime('NN:SS',now)+'计时器已中止.');end;
3.2运行结果与分析
48:19in Timer1Timer before sleep48:20Timer_work.tag=1
48:20Timer1.tag=0
48:20in Timer1Timer before sleep48:21Timer_work.tag=1
48:21Timer1.tag=0
48:21in Timer1Timer before sleep48:22Timer_work.tag=1
48:22Timer1.tag=0
48:22in Timer1Timer before sleep48:23Timer_work.tag=1
48:23Timer1.tag=0
48:23in Timer1Timer before sleep48:24Timer_work.tag=1
48:24Timer1.tag=0
48:24in Timer1Timer before sleep48:25Timer_work.tag=1
48:25Timer1.tag=0
48:25in Timer1Timer before sleep48:26Timer_work.tag=1
48:26Timer1.tag=0
48:26in Timer1Timer before sleep48:27Timer_work.tag=1
48:27Timer1.tag=0
48:27in Timer1Timer before sleep48:28Timer_work.tag=1
48:28Timer1.tag=0
48:28in Timer1Timer before sleep48:29Timer_work.tag=1
48:29Timer1.tag=0
48:29in Timer1Timer before sleep48: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函数。