ttimer其实就是一个接受窗口wm_timer消息的不可见窗口。把它放在线程里面创建,再线程里面监测消息队列,响应wm_timer消息,用getmessage比peekmessape或者application.processmessages好,因为线程消息队列没有消息的时候,就不会空循环,不会累坏cpu:)如果你非要用线程来实现,也可以,给你个类,线程timer计时的。 //////////////////////////////////////// unit Unit2;interfaceuses Classes,ExtCtrls,messages,windows;type TTimerThread = class(TThread) private Timer:TTimer; protected procedure Execute; override; public procedure Resume; procedure Suspend; procedure SetInterval(Interval:integer); function GetInterval:integer; constructor create(suspended:boolean;Interval:integer;OnTimerProc:TNotifyevent); destructor destroy;override; end;implementation { TTimerThread }constructor TTimerThread.create(suspended: boolean;Interval:integer;OnTimerProc:TNotifyevent); begin inherited create(true); timer:=ttimer.Create(nil); timer.OnTimer:=ontimerproc; timer.Interval:=interval; timer.Enabled:=false; if not suspended then resume; end;destructor TTimerThread.destroy; begin timer.Free; inherited; end;procedure TTimerThread.Execute; var msg:tmsg; begin while (not terminated)and getmessage(msg,0,0,0) do begin translatemessage(msg); dispatchmessage(msg); end; end;function TTimerThread.GetInterval: integer; begin result:=timer.Interval; end;procedure TTimerThread.Resume; begin timer.Enabled:=true; inherited;end; procedure TTimerThread.SetInterval(Interval: integer); begin timer.Interval:=interval; end;procedure TTimerThread.Suspend; begin timer.Enabled:=false; inherited;end;end.
线程中一般用Sleep()就可以了,还用tiomer反而效率不高。。
这个类几乎不用更改了,只要你在任何时候指定interval和在创建的时候指定了响应ontimer的过程就可以了。暂停监控的时候用suspend,继续监控用resume,停止监控free就可以了。 下面是使用示范: ///////////////////////// unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure Button2Click(Sender: TObject); private { Private declarations } procedure OnTimer(sender:tobject); public { Public declarations } end;var Form1: TForm1;implementation uses unit2; var t:ttimerthread; {$R *.dfm}procedure TForm1.Button1Click(Sender: TObject); begin t.Suspend; end;procedure TForm1.OnTimer(sender: tobject); begin beep; end;procedure TForm1.FormCreate(Sender: TObject); begin t:=ttimerthread.create(true,1000,ontimer); t.FreeOnTerminate:=true; t.Resume; end;procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin t.Terminate; end;procedure TForm1.Button2Click(Sender: TObject); begin t.Resume; end;end.
//上面的有问题,不能实现真正的线程控制的定时器。 //换下面的吧: unit Unit3;interfaceuses Classes,sysutils,syncobjs;type TThreadTimer = class(TThread) private cs:tcriticalsection; Interval:integer; OnTimer:TNotifyEvent; protected procedure Execute; override; public function GetInterval:integer; procedure SetInterval(Interval:integer); procedure SetOntimer(Ontimer:TNotifyEvent); function GetOnTimer:TNotifyEvent; ///////// procedure SetEnabled(Enabled:boolean); function GetEnabled:boolean; ///////// constructor Create(Interval:integer;Ontimer:TNotifyEvent); destructor Destroy;override; end;implementation { TThreadTimer }constructor TThreadTimer.Create(Interval: integer; Ontimer: TNotifyEvent); begin inherited create(true); self.Interval:=interval; self.OnTimer:=ontimer; freeonterminate:=true; cs:=tcriticalsection.Create;end;destructor TThreadTimer.Destroy; begin cs.Free; inherited; end;procedure TThreadTimer.Execute; var i:integer; begin while not terminated do begin cs.Enter; i:=interval; cs.Leave; sleep(i); cs.Enter; try if assigned(ontimer)then ontimer(self); finally cs.Leave; end; end; end;function TThreadTimer.GetEnabled: boolean; begin result:=self.Suspended; end;function TThreadTimer.GetInterval: integer; begin cs.Enter; result:=interval; cs.Leave; end;function TThreadTimer.GetOnTimer: TNotifyEvent; begin cs.Enter; result:=ontimer; cs.Leave; end;procedure TThreadTimer.SetEnabled(Enabled: boolean); begin if enabled then resume else suspend; end;procedure TThreadTimer.SetInterval(Interval: integer); begin cs.Enter; self.Interval:=interval; cs.Leave; end;procedure TThreadTimer.SetOntimer(Ontimer: TNotifyEvent); begin cs.Enter; self.OnTimer:=ontimer; cs.Leave; end; end. //////////////////////////////////////////////// //测试代码如下: unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,unit3;type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } procedure OnTimer(sender:tobject); public { Public declarations } t1:tthreadtimer; end;var Form1: TForm1;implementation {$R *.dfm}procedure TForm1.Button1Click(Sender: TObject); begin t1.SetEnabled(false); end;procedure TForm1.OnTimer(sender: tobject); begin beep; end;procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin t1.Terminate; end;procedure TForm1.Button2Click(Sender: TObject); begin t1.SetEnabled(true); end;procedure TForm1.Button3Click(Sender: TObject); begin sleep(10000);//主线程死锁也不会影响定时线程。self.ontimer依然会被调用。 end;procedure TForm1.FormCreate(Sender: TObject); begin t1:=tthreadtimer.Create(1000,ontimer); t1.SetEnabled(true); end;end.
////////////////////////////////////////
unit Unit2;interfaceuses
Classes,ExtCtrls,messages,windows;type
TTimerThread = class(TThread)
private
Timer:TTimer; protected
procedure Execute; override;
public
procedure Resume;
procedure Suspend;
procedure SetInterval(Interval:integer);
function GetInterval:integer; constructor create(suspended:boolean;Interval:integer;OnTimerProc:TNotifyevent);
destructor destroy;override;
end;implementation
{ TTimerThread }constructor TTimerThread.create(suspended: boolean;Interval:integer;OnTimerProc:TNotifyevent);
begin
inherited create(true);
timer:=ttimer.Create(nil);
timer.OnTimer:=ontimerproc;
timer.Interval:=interval;
timer.Enabled:=false;
if not suspended then
resume;
end;destructor TTimerThread.destroy;
begin
timer.Free;
inherited;
end;procedure TTimerThread.Execute;
var
msg:tmsg;
begin
while (not terminated)and getmessage(msg,0,0,0) do
begin
translatemessage(msg);
dispatchmessage(msg);
end;
end;function TTimerThread.GetInterval: integer;
begin
result:=timer.Interval;
end;procedure TTimerThread.Resume;
begin
timer.Enabled:=true;
inherited;end;
procedure TTimerThread.SetInterval(Interval: integer);
begin
timer.Interval:=interval;
end;procedure TTimerThread.Suspend;
begin
timer.Enabled:=false;
inherited;end;end.
下面是使用示范:
/////////////////////////
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
procedure OnTimer(sender:tobject);
public
{ Public declarations }
end;var
Form1: TForm1;implementation
uses
unit2;
var
t:ttimerthread;
{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
t.Suspend;
end;procedure TForm1.OnTimer(sender: tobject);
begin
beep;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
t:=ttimerthread.create(true,1000,ontimer);
t.FreeOnTerminate:=true;
t.Resume;
end;procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
t.Terminate;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
t.Resume;
end;end.
//换下面的吧:
unit Unit3;interfaceuses
Classes,sysutils,syncobjs;type
TThreadTimer = class(TThread)
private
cs:tcriticalsection;
Interval:integer;
OnTimer:TNotifyEvent; protected
procedure Execute; override;
public
function GetInterval:integer;
procedure SetInterval(Interval:integer);
procedure SetOntimer(Ontimer:TNotifyEvent);
function GetOnTimer:TNotifyEvent;
/////////
procedure SetEnabled(Enabled:boolean);
function GetEnabled:boolean;
/////////
constructor Create(Interval:integer;Ontimer:TNotifyEvent);
destructor Destroy;override;
end;implementation
{ TThreadTimer }constructor TThreadTimer.Create(Interval: integer; Ontimer: TNotifyEvent);
begin
inherited create(true);
self.Interval:=interval;
self.OnTimer:=ontimer;
freeonterminate:=true;
cs:=tcriticalsection.Create;end;destructor TThreadTimer.Destroy;
begin
cs.Free;
inherited;
end;procedure TThreadTimer.Execute;
var
i:integer;
begin
while not terminated do
begin
cs.Enter;
i:=interval;
cs.Leave;
sleep(i);
cs.Enter;
try
if assigned(ontimer)then
ontimer(self);
finally
cs.Leave;
end;
end;
end;function TThreadTimer.GetEnabled: boolean;
begin
result:=self.Suspended;
end;function TThreadTimer.GetInterval: integer;
begin
cs.Enter;
result:=interval;
cs.Leave;
end;function TThreadTimer.GetOnTimer: TNotifyEvent;
begin
cs.Enter;
result:=ontimer;
cs.Leave;
end;procedure TThreadTimer.SetEnabled(Enabled: boolean);
begin
if enabled then
resume
else
suspend;
end;procedure TThreadTimer.SetInterval(Interval: integer);
begin
cs.Enter;
self.Interval:=interval;
cs.Leave;
end;procedure TThreadTimer.SetOntimer(Ontimer: TNotifyEvent);
begin
cs.Enter;
self.OnTimer:=ontimer;
cs.Leave;
end;
end.
////////////////////////////////////////////////
//测试代码如下:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,unit3;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure OnTimer(sender:tobject);
public
{ Public declarations }
t1:tthreadtimer;
end;var
Form1: TForm1;implementation
{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
t1.SetEnabled(false);
end;procedure TForm1.OnTimer(sender: tobject);
begin
beep;
end;procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
t1.Terminate;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
t1.SetEnabled(true);
end;procedure TForm1.Button3Click(Sender: TObject);
begin
sleep(10000);//主线程死锁也不会影响定时线程。self.ontimer依然会被调用。
end;procedure TForm1.FormCreate(Sender: TObject);
begin
t1:=tthreadtimer.Create(1000,ontimer);
t1.SetEnabled(true);
end;end.