zoukankan      html  css  js  c++  java
  • Delphi定时器控件TTimer“一睡不醒”问题研究

    1,试验1—基础代码

    1.1页面控件与代码

    定时器

    Timer1

    Timer_work

    Interval

    1000

    1500

    Enabled

    True

    True

    Ontimer事件

      if Timer1.Tag=1 then exit;  //tag=1表示正在忙
    
     
    
      Timer1.Tag := 1;
    
      try
    
        memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' + intToStr(Timer_work.tag));
    
      finally
    
        Timer1.Tag := 0;
    
      end;

      

    if Timer_work.Tag=1 then exit;  //tag=1表示正在忙
    
      Timer_work.Tag := 1;
    
      try
    
        memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' + intToStr(Timer1.tag));
    
      finally
    
        Timer_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;
    
      try
    
        application.ProcessMessages;
    
        sleep(1000);    memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer_work.tag=' + intToStr(Timer_work.tag));
    
      finally
    
        Timer1.Tag := 0;
    
      end;
      if Timer_work.Tag=1 then exit;  //tag=1表示正在忙
    
      Timer_work.Tag := 1;
    
      try
    
        application.ProcessMessages;
    
        sleep(1000);    memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' + intToStr(Timer1.tag));
    
      finally
    
        Timer_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;
    
      try
    
    application.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));
    
      finally
    
    Timer1.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;
    
      try
    
    application.ProcessMessages;
    
     
    
        sleep(1000);    
    memo1.Lines.Add(formatDatetime('NN:SS',now)+'Timer1.tag=' + intToStr(Timer1.tag)); finally Timer_work.Tag := 0; 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函数。
  • 相关阅读:
    Unity C# 反编译
    java finalize方法总结、GC执行finalize的过程
    Android性能调优篇之探索垃圾回收机制
    深入理解JVM(一)——JVM内存模型
    Android性能调优篇之探索JVM内存分配
    HashMap实现原理分析
    [干货]2017已来,最全面试总结——这些Android面试题你一定需要
    2017年最全的30个Android面试题,你将如何回答?
    Android2017进阶知识点、面试题及答案(精选版)
    Android2017最新面试题(3-5年经验个人面试经历)
  • 原文地址:https://www.cnblogs.com/jackkwok/p/10899273.html
Copyright © 2011-2022 走看看