怎么在多线程中使用定时器啊? API里面Timer相关的函数。直接可以在delphi的帮助里面查到的。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 type TMyThread = class(TThread) private FTimer:TTimer; procedure TimerProc(Sender: TObject); protected procedure Execute;override; public constructor Create;override; procedure KillIt;//结束 end;implementation procedure TMyThread.TimerProc(Sender: TObject); begin ... end; procedure TMyThread.KillIt; begin PostThreadMessage(ThreadNo,WM_QUIT,0,0); end;procedure TMyThread.Execute;begin FTimer:=TTimer.Create(nil); try FTimer.Enabled:=false;//需要用的时候Enabled设置为True即可。 FTimer.OnTimer:=TimerProc; while GetMessage(MsgRec, 0, 0, 0) do begin TranslateMessage(MsgRec); DispatchMessage(MsgRec) end; Terminate; finally FTimer.Free; end;end;要结束的话,往线程的Handle发送一个WM_QUIT消息,本例当中调用KillIt var T: TMyThread; begin ... T.KillIt; end; 楼上的就行了, 在thread.create 的时候应创建timer对象及设置timer 的属性 Thread.Create当中创建的会是在当前线程(主线程)当中执行的,在Thread.Execute当中创建的才是在该线程当中的。也就是WM_TIMER被投递的线程会是不一样的。否则的话,就不是线程当中的Timer. //请教一下僵哥,为什么在线程的构造函数中创建Timer后,当线程中有时间消息时就会把WM_TIMER投递给主线程队列呢?//另外,僵哥,用线程周期性阻塞是不是也可以//线程类unit Unit2;interfaceuses Classes,sysutils,SyncObjs,Dialogs;type TTest = class(TThread) private { Private declarations } FSum:Integer; procedure UpdateCaption; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); end;implementationuses Unit1;procedure TTest.UpdateCaption;begin Form1.Edit1.Text := Inttostr(FSum); showmessage('Sum Process End');end;procedure TTest.Execute;begin//必须循环来判断Terminated标志 while not Terminated do begin FSum:=FSum+1;//这里可以执行其它独立的任务,例如生成带有独立任务的线程 case QuitEvent.WaitFor(60*100) of //阻塞时间,即Timer.Interval wrSignaled, wrAbandoned: Terminate; end; Synchronize(UpdateCaption);//实现问题2,把函数放在这里,是为了更直观地看到当前执行的结果 end; { Place thread code here }end;constructor TTest.Create(CreateSuspended: Boolean);begin inherited; FSum:=0;end;end.//主线程代码unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,SyncObjs;type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; procedure NotifySumThreadsToQuit;var Form1: TForm1; QuitEvent: TEvent;//事件说白了就是一个全局的布尔变量,用SetEvent置为一种状态,便于在线程循环时根据该标识来将线程中止implementationuses Unit2;{$R *.dfm}procedure NotifySumThreadsToQuit;begin QuitEvent.SetEvent;//置信号end;procedure TForm1.Button1Click(Sender: TObject);var Thd:TTest;begin Thd:=TTest.Create(True); Thd.FreeOnTerminate:=False; Thd.Resume;end;procedure TForm1.Button2Click(Sender: TObject);begin NotifySumThreadsToQuit//通知线程结束end;initialization QuitEvent := TEvent.Create(nil,true,false,'SumProcessEnd');//创建事件finalization QuitEvent.Free;//释放事件end. to 楼上。消息队列是以线程为基础的。线程构造函数实际只是由主线程调用的一个过程。其代码是在主线程中运行的。因此,在线程构造函数中创建一个Timer对象实际就是主线程创建了一个Timer对象,因此WM_TIMER消息只会进入主线程的消息队。真正的线程执行代码只会在线程对象的Execute部分存在。 明白了,明白了,谢谢蒲石大哥!刚才被Delphi封装的线程类迷惑了!看了一下其类实现,明白了!就是要把创建Timer的过程写在CreateThread的回调函数中才能达到目的! 这问题,可能更好的方法是使用 CreateWaitableTimer WaitableTimer实际也需要一个wait阻塞或者不断循环。相比之下多媒体定时器应该是比较好的选择,多媒体定时器本身就是一个线程。 while GetMessage(MsgRec, 0, 0, 0) do begin TranslateMessage(MsgRec); DispatchMessage(MsgRec) end;VCL消息处理^_^ LZ是想要线程安全的,2楼给的确是非线程安全的,其中陷阱不少哦最好的方法是在线程执行过程中自己手动创建一个窗口。那么这个窗口的消息投递就会在这个线程中了。你想要TIMER,那就可以SETWINDOWTIMRE,在消息循环中相应WM_Timer我以前倒是写过一个这样的代码,不记得在不在我的BLOG里了。有星期可以去看看。 最好的方法是在线程执行过程中自己手动创建一个窗口。那么这个窗口的消息投递就会在这个线程中了。-------------------------------------------------------------------------------- 楼上的,自己去看看Delphi的TTimer是怎么实现的(没记错的话,是通过AllocateHandle创建了一个窗体,也就是说是TTimer就是通过窗体响应WM_TIMER消息实现的)。 求教一个excel导入SqlServer的问题!! 菜鸟问题,可能是语法错误,送分! 提问,关于配合银行代理收费的问题? opendialog问题请教 如何用程序来实现:设置打印机页面设置中纸张的方向?请高手帮忙! 请问各位高手: 运行时提示BDE初始化错误,代号$3E06, 请问如何解决? 问一个极菜的问题!!! 怎么获得CheckListBox的当前鼠标选中项的string值,不是Checked项 VC6.0和VC.net有什么区别? 武汉JAVA/android培训最优选择--传智播客武汉分校! tabsheet2窗口无法使用
TMyThread = class(TThread)
private
FTimer:TTimer;
procedure TimerProc(Sender: TObject);
protected
procedure Execute;override;
public
constructor Create;override;
procedure KillIt;//结束
end;
implementation
procedure TMyThread.TimerProc(Sender: TObject);
begin
...
end;
procedure TMyThread.KillIt;
begin
PostThreadMessage(ThreadNo,WM_QUIT,0,0);
end;
procedure TMyThread.Execute;
begin
FTimer:=TTimer.Create(nil);
try
FTimer.Enabled:=false;//需要用的时候Enabled设置为True即可。
FTimer.OnTimer:=TimerProc;
while GetMessage(MsgRec, 0, 0, 0) do begin
TranslateMessage(MsgRec);
DispatchMessage(MsgRec)
end;
Terminate;
finally
FTimer.Free;
end;
end;
要结束的话,往线程的Handle发送一个WM_QUIT消息,本例当中调用KillIt var
T: TMyThread;
begin
...
T.KillIt;
end;
//另外,僵哥,用线程周期性阻塞是不是也可以//线程类
unit Unit2;interfaceuses
Classes,sysutils,SyncObjs,Dialogs;
type
TTest = class(TThread)
private
{ Private declarations }
FSum:Integer;
procedure UpdateCaption;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
end;
implementation
uses Unit1;procedure TTest.UpdateCaption;
begin
Form1.Edit1.Text := Inttostr(FSum);
showmessage('Sum Process End');
end;procedure TTest.Execute;
begin
//必须循环来判断Terminated标志
while not Terminated do
begin
FSum:=FSum+1;//这里可以执行其它独立的任务,例如生成带有独立任务的线程
case QuitEvent.WaitFor(60*100) of //阻塞时间,即Timer.Interval
wrSignaled, wrAbandoned: Terminate;
end;
Synchronize(UpdateCaption);//实现问题2,把函数放在这里,是为了更直观地看到当前执行的结果
end;
{ Place thread code here }
end;constructor TTest.Create(CreateSuspended: Boolean);
begin
inherited;
FSum:=0;
end;end.
//主线程代码
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,SyncObjs;type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
procedure NotifySumThreadsToQuit;var
Form1: TForm1;
QuitEvent: TEvent;//事件说白了就是一个全局的布尔变量,用SetEvent置为一种状态,便于在线程循环时根据该标识来将线程中止
implementationuses Unit2;{$R *.dfm}procedure NotifySumThreadsToQuit;
begin
QuitEvent.SetEvent;//置信号
end;procedure TForm1.Button1Click(Sender: TObject);
var
Thd:TTest;
begin
Thd:=TTest.Create(True);
Thd.FreeOnTerminate:=False;
Thd.Resume;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
NotifySumThreadsToQuit//通知线程结束
end;initialization
QuitEvent := TEvent.Create(nil,true,false,'SumProcessEnd');//创建事件finalization
QuitEvent.Free;//释放事件
end.
因此,在线程构造函数中创建一个Timer对象实际就是主线程创建了一个Timer对象,因此WM_TIMER消息只会进入主线程的消息队。真正的线程执行代码只会在线程对象的Execute部分存在。
刚才被Delphi封装的线程类迷惑了!
看了一下其类实现,明白了!就是要把创建Timer的过程写在CreateThread的回调函数中才能达到目的!
TranslateMessage(MsgRec);
DispatchMessage(MsgRec)
end;VCL消息处理^_^
最好的方法是在线程执行过程中自己手动创建一个窗口。那么这个窗口的消息投递就会在这个线程中了。你想要TIMER,那就可以SETWINDOWTIMRE,在消息循环中相应WM_Timer我以前倒是写过一个这样的代码,不记得在不在我的BLOG里了。有星期可以去看看。
--------------------------------------------------------------------------------
楼上的,自己去看看Delphi的TTimer是怎么实现的(没记错的话,是通过AllocateHandle创建了一个窗体,也就是说是TTimer就是通过窗体响应WM_TIMER消息实现的)。