Delphi 线程Timer (TThreadTimer)
<p>delphi 自带的Timer控件,使用方便,但它的 OnTimer 事件是在主线程中引发的。</p><p>如果在事件中执行较耗时的代码,会引起主界面假死。故实现一个线程的Timer就有必要了。</p>
<p>TThreadTimer 基于 TSimpleThread 继承而来。</p>
<p>本例源码下载</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">unit</span><span style="color: rgba(0, 0, 0, 1)"> uThreadTimer;
</span><span style="color: rgba(0, 0, 255, 1)">interface</span>
<span style="color: rgba(0, 0, 255, 1)">uses</span><span style="color: rgba(0, 0, 0, 1)">
uSimpleThread;
</span><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
TThreadTimer </span>= <span style="color: rgba(0, 0, 255, 1)">class</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 提前申明 TThreadTimer 是一个类</span>
<span style="color: rgba(0, 0, 0, 1)">
TOnThreadTimer </span>= <span style="color: rgba(0, 0, 255, 1)">procedure</span>(Sender: TThreadTimer) <span style="color: rgba(0, 0, 255, 1)">of</span> <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 此处就可以引用 TThreadTimer,这种写法避免将 Sender 写为 TObject;</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为什么要写这个 sender ,主要是为了区别是谁引发了事件,并且 sender 上可以带参数</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 方便进一步使用</span>
<span style="color: rgba(0, 0, 0, 1)">
TThreadTimer </span>=<span style="color: rgba(0, 0, 0, 1)"> Class(TSimpleThread)
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)">
FInterval: Cardinal;
FOnThreadTimer: TOnThreadTimer;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> CountTimer;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> DoCountTimer;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> SetInterval(val: Cardinal);
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> SetOnThreadTimer(val: TOnThreadTimer);
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span> DoOnThreadTimer; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 请学习此写法</span>
<span style="color: rgba(0, 0, 255, 1)">public</span>
<span style="color: rgba(0, 0, 255, 1)">constructor</span> <span style="color: rgba(0, 0, 255, 1)">Create</span>(AAllowActiveX: Boolean = false); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> AAlowActiveX 在父类中有说明</span>
<span style="color: rgba(0, 0, 255, 1)">procedure</span> StartThread; <span style="color: rgba(0, 0, 255, 1)">override</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 重载父类的 StartThread</span>
<span style="color: rgba(0, 0, 255, 1)">property</span> Interval: Cardinal <span style="color: rgba(0, 0, 255, 1)">read</span> FInterval <span style="color: rgba(0, 0, 255, 1)">write</span> SetInterval <span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这个 default 1000 是给人看的,不会产生实际作用。</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 故还需要在 Create 事件中指定 FInterval:=1000;</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果可视化控件的 published 块中,此值会显示在属性编辑框中</span>
<span style="color: rgba(0, 0, 255, 1)">property</span> OnThreadTimer: TOnThreadTimer <span style="color: rgba(0, 0, 255, 1)">read</span> FOnThreadTimer <span style="color: rgba(0, 0, 255, 1)">write</span><span style="color: rgba(0, 0, 0, 1)"> SetOnThreadTimer;
End;
</span><span style="color: rgba(0, 0, 255, 1)">implementation</span>
<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> TThreadTimer </span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TThreadTimer.CountTimer;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
ExeProcInThread(DoCountTimer);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将 DoCountTimer 置入线程中去执行</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这是 TSimpleThread 的用法</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">constructor</span> TThreadTimer.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">(AAllowActiveX: Boolean);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">inherited</span> <span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">(AAllowActiveX);
FInterval :</span>= <span style="color: rgba(128, 0, 128, 1)">1000</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认间隔时间为 1 秒</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TThreadTimer.DoCountTimer;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> WaitStop <span style="color: rgba(0, 0, 255, 1)">then</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这是父类的一个属性,表示线程现在需要停止了。</span>
<span style="color: rgba(0, 0, 0, 1)"> exit;
SleepExceptStopped(FInterval); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> sleep 指定的时间,如果中途接到退出指令,则马上响应。</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 父类中有源码,可看一看</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(0, 0, 255, 1)">not</span> WaitStop <span style="color: rgba(0, 0, 255, 1)">then</span>
<span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
DoOnThreadTimer; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引发时间到事件</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
CountTimer; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 再次在线程中执行 DoCountTimer;</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 父类已经设计好了,就这样简单地调用,即可实现在线程中执行本过程,但又不会引起“递归”</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TThreadTimer.DoOnThreadTimer;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> Assigned(FOnThreadTimer) <span style="color: rgba(0, 0, 255, 1)">then</span><span style="color: rgba(0, 0, 0, 1)">
FOnThreadTimer(Self);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把这句写为一个过程,看似啰嗦,但为了程序可读性,是值得的。</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TThreadTimer.StartThread;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">inherited</span><span style="color: rgba(0, 0, 0, 1)">;
CountTimer; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 启动计时</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TThreadTimer.SetInterval(val: Cardinal);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
FInterval :</span>=<span style="color: rgba(0, 0, 0, 1)"> val;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TThreadTimer.SetOnThreadTimer(val: TOnThreadTimer);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
FOnThreadTimer :</span>=<span style="color: rgba(0, 0, 0, 1)"> val;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">.
uThreadTimer.pas</span></pre>
</div>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
好的代码像粥一样,都是用时间熬出来的<br><br>
来源:https://www.cnblogs.com/jijm123/p/11747298.html
頁:
[1]