Delphi线程定时器

(*

自己编写的线程计时器,没有采用消息机制,很有效

Cobbler续写

不用 TTimer 的原因:

要说TTimer类的使用问题,先要说一下它响应用户定义的回调函数(OnTimer)的方法。
TTimer拥有一个HWnd类型的成员变量FWindowHandle,用于捕捉系统消息。
TTimer在Enable的情况下,每隔Interval时间,就抛一个系统消息WM_TIMER,FWindowHandle捕捉到这个消息后,
就会执行用户的回调函数,实现用户需要的功能。就是这个消息机制引发了下面两个问题:

问题1: 还不算严重,TTimer与系统共用一个消息队列,也就是说,在用户回调函数处理完之前,
所有的系统消息都处于阻塞状态,包括界面的更新的消息。
如果你的回调函数瞬间执行完毕那就一切看着还正常,如果你要执行一个复杂耗时的操作,
比如数据库查询什么的(万一遇到数据库联接不正常,等待20秒),
那你的界面就必死无疑,直到回调函数执行完。如果是后台系统还好,
要是给用户使用的就没法交待了。即使你在子线程里面使用也不会解决的。

问题2: 一般系统定义消息的优先级比用户定义消息的优先级要低。
在子线程中使用TTimer时,如果线程间通信也大量使用自定义消息,
并且用户定义自己的消息处理函数,那WM_TIMER经常就会被丢弃了,
计时器就彻底失效了。

摘抄自网络

*)

unit UntThreadTimer;

interface

uses
Windows, Classes,Winapi.Messages;

type
TTimerStatus = (TS_ENABLE, TS_CHANGEINTERVAL, TS_DISABLE, TS_SETONTIMER);
TThreadedTimer = class;
TTimerThread = class;
PTimerThread = ^TTimerThread;

TTimerThread = class(TThread)
OwnerTimer: TThreadedTimer;
Interval: DWord;
Enabled : Boolean;
Status : TTimerStatus;
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
procedure Execute; override;
procedure DoTimer;
end;

TThreadedTimer = class(TComponent)
private
FHandle: THandle;
FEnabled: Boolean;
FInterval: DWord;
FOnTimer: TNotifyEvent;
FTimerThread: TTimerThread;
FThreadPriority: TThreadPriority;
protected
procedure UpdateTimer;
procedure SetEnabled(Value: Boolean);
procedure SetInterval(Value: DWord);
procedure SetOnTimer(Value: TNotifyEvent);
procedure Timer; dynamic;
public
constructor Create(AHandle: THandle; AOwner: TComponent);
destructor Destroy; override;
published
property Enabled: Boolean read FEnabled write SetEnabled default True;
property Interval: DWord read FInterval write SetInterval default 1000;
property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
end;

implementation

procedure WakeupDownThrdproc(const evenFlag: Integer); stdcall;
begin

end;
{TTimerThread}
constructor TTimerThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
Interval := 1000;
Enabled := False;
Status := TS_DISABLE;
end;

destructor TTimerThread.Destroy;
begin
inherited;
end;

procedure TTimerThread.Execute;
begin
inherited;
while not Terminated do
begin
//SleepEx(Interval, True);
if (not Terminated) and (Status = TS_ENABLE) then Synchronize(DoTimer);
if Status <> TS_ENABLE then
begin
case Status of
TS_CHANGEINTERVAL:
begin
Status := TS_ENABLE;
SleepEx(0,True);
end;
TS_DISABLE:
begin
Status := TS_ENABLE;
SleepEx(0, True);
if not Terminated then Suspend;
end;
TS_SETONTIMER:
begin
Status := TS_ENABLE;
end else
Status := TS_ENABLE;
end;
end;
SleepEx(Interval, True);
end;
end;

procedure TTimerThread.DoTimer;
begin
OwnerTimer.Timer;
end;
{TThreadedTimer}
constructor TThreadedTimer.Create(AHandle: THandle; AOwner: TComponent);
begin
inherited Create(AOwner);
FHandle := AHandle;
FInterval := 1000;
FThreadPriority := tpNormal;
FTimerThread := TTimerThread.Create(true);
FTimerThread.OwnerTimer := self;
end;

destructor TThreadedTimer.Destroy;
begin
inherited Destroy;
FTimerThread.Terminate;
QueueUserAPC(@WakeupDownThrdproc, FTimerThread.Handle, DWORD(FTimerThread));
FTimerThread.Free;
end;

procedure TThreadedTimer.UpdateTimer;
begin
if (FEnabled = False) then
begin
FTimerThread.OwnerTimer := Self;
FTimerThread.Interval := FInterval;
FTimerThread.Priority := FThreadPriority;
FTimerThread.Resume;
end;
if (FEnabled = True) then
begin
QueueUserAPC(@WakeupDownThrdproc, FTimerThread.Handle, DWORD(FTimerThread));
end;
end;

procedure TThreadedTimer.SetEnabled(Value: Boolean);
begin
if Value <> FEnabled then
begin
FEnabled := Value;
if Value then
begin
FTimerThread.Status := TS_ENABLE;
FTimerThread.Resume;
end
else
begin
FTimerThread.Status := TS_DISABLE;
QueueUserAPC(@WakeupDownThrdproc, FTimerThread.Handle, DWORD(FTimerThread));
end;
end;
end;

procedure TThreadedTimer.SetInterval(Value: DWord);
begin
if Value <> FInterval then
begin
if (not Enabled) then
begin
FInterval := Value;
FTimerThread.Interval := FInterval;
end
else
begin
FInterval := Value;
FTimerThread.Interval := FInterval;
FTimerThread.Status := TS_CHANGEINTERVAL;
QueueUserAPC(@WakeupDownThrdproc, FTimerThread.Handle, DWORD(FTimerThread));
end;
end;
end;

procedure TThreadedTimer.SetOnTimer(Value: TNotifyEvent);
begin
FOnTimer := Value;
end;

procedure TThreadedTimer.Timer;
var
Msg: TMessage;
begin
Msg.Msg := WM_USER+100;
//if Assigned(FOnTimer) then FOnTimer(Self);
SendMessage(FHandle,msg.Msg,0,0);
end;

end.

时间: 2024-07-29 19:06:16

Delphi线程定时器的相关文章

TMsgThread, TCommThread -- 在delphi线程中实现消息循环(105篇博客,好多研究消息的文章)

在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使用很方便,但是有时候我们需要在线程类中使用消息循环,delphi没有提供. 花了两天的事件研究了一下win32的消息系统,写了一个线程内消息循环的测试. 但是没有具体应用过,贴出来给有这方面需求的DFW参考一下.希望大家和我讨论. {----------------------------------------------------------------------------- Unit

delphi 线程教学第六节:TList与泛型

第六节: TList 与泛型 TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本): FooList.Zip unit uFooList; interface uses   Generics.Collections; type   TFooList <T>= class(TList<T>)   private     procedure FreeAllItems;   

多线程的基本概念和Delphi线程对象Tthread介绍

多线程的基本概念和Delphi线程对象Tthread介绍 作者:xiaoru WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行时间和资源,或者说,把CPU 时间划成片,每个片分给不同的线程,这样,每个线程轮流的“挂起”和“唤醒”,由于时间片很小,给人的感觉是同时运行的. 多线程带来如下好处: 1)避免瓶颈: 2)并行操作: 3)提高效率:多线程的两个概念: 1) 进程:也称任务,程序载入内存,并分配资源,称为“一个进程”. 注意

在delphi线程中实现消息循环

http://delphi.cjcsoft.net//viewthread.php?tid=635 在delphi线程中实现消息循环 Delphi的TThread类使用很方便,但是有时候我们需要在线程类中使用消息循环,delphi没有提供. 花了两天的事件研究了一下win32的消息系统,写了一个线程内消息循环的测试. 但是没有具体应用过,贴出来给有这方面需求的DFW参考一下.希望大家和我讨论. {--------------------------------------------------

121 Python程序中的线程操作-线程定时器

目录 一.线程定时器 二.用法 一.线程定时器 线程定时器也是定时器,就是定时之后开启一条线程 二.用法 ''' 线程定时器,就是规定时间后开启一条线程 ''' def task(): print('线程执行了') time.sleep(2) print('线程结束了') t = Timer(4,task) # 间隔时间, 功能函数 t.start() 原文地址:https://www.cnblogs.com/XuChengNotes/p/11553061.html

Delphi线程类 DIY(把类指针作为参数传进去,就可以执行类里面的方法啦)

Delphi 封装了一个很强大的线程类 TThread, 我们也自己动手制作一个简单的线程类 首先Type一个类 [delphi] view plain copy type TwwThread = class constructor Create; overload; destructor Destroy; override; private m_hThread: THandle;     //线程 m_ThreadID : TThreadID; public procedure Execute

Delphi线程的终止

当线程对象的Execute()执行完毕的时候,我们就认为此线程终止了.这时候,它会调用Delphi的一个标准例程EndThread(),这个例程再调用API函数ExitThread().由ExitThread()来清除线程所占用的栈. 当结束使用TThread对象的时候,应该确保已经把这个Object Pascal对象从内存中清除了.这才能确保所有内存占有都释放掉,尽管在进程终止时候会自动清除所有的线程对象,但是及时清除已经不再使用的对象,可以使内存的使用效率提高.利用将FreeOnTermin

Delphi 线程Timer (TThreadTimer)

delphi 自带的Timer控件,使用方便,但它的 OnTimer 事件是在主线程中引发的. 如果在事件中执行较耗时的代码,会引起主界面假死.故实现一个线程的Timer就有必要了. TThreadTimer 基于 TSimpleThread 继承而来. 本例源码下载 unit uThreadTimer; interface uses uSimpleThread; type TThreadTimer = class; // 提前申明 TThreadTimer 是一个类 TOnThreadTime

Delphi线程池

unit uThreadPool; {   aPool.AddRequest(TMyRequest.Create(RequestParam1, RequestParam2, ...)); } interfaceuses  Windows,  Classes; // 是否记录日志// {$DEFINE NOLOGS} type  TCriticalSection = class(TObject)  protected    FSection: TRTLCriticalSection;  publi