怎么在多线程中使用定时器啊?

yangsf004 2008-12-18 03:46:33
如题!
...全文
815 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
etomahawk 2009-02-23
  • 打赏
  • 举报
回复
最好的方法是在线程执行过程中自己手动创建一个窗口。那么这个窗口的消息投递就会在这个线程中了。
--------------------------------------------------------------------------------
楼上的,自己去看看Delphi的TTimer是怎么实现的(没记错的话,是通过AllocateHandle创建了一个窗体,也就是说是TTimer就是通过窗体响应WM_TIMER消息实现的)。
simb 2009-02-23
  • 打赏
  • 举报
回复
LZ是想要线程安全的,2楼给的确是非线程安全的,其中陷阱不少哦
最好的方法是在线程执行过程中自己手动创建一个窗口。那么这个窗口的消息投递就会在这个线程中了。你想要TIMER,那就可以SETWINDOWTIMRE,在消息循环中相应WM_Timer我以前倒是写过一个这样的代码,不记得在不在我的BLOG里了。有星期可以去看看。
ly_liuyang 2009-01-09
  • 打赏
  • 举报
回复
while GetMessage(MsgRec, 0, 0, 0) do begin
TranslateMessage(MsgRec);
DispatchMessage(MsgRec)
end;

VCL消息处理^_^
UndefinedCoder 2009-01-05
  • 打赏
  • 举报
回复
领可用分来也。
xihii6 2009-01-05
  • 打赏
  • 举报
回复
学习了。
ZuoBaoquan 2009-01-02
  • 打赏
  • 举报
回复
@zwjchina, 谢谢!学习了。
lonelyriver 2009-01-02
  • 打赏
  • 举报
回复
僵哥 2008-12-20
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zwjchina 的回复:]
这问题,可能更好的方法是使用 CreateWaitableTimer
[/Quote]
WaitableTimer实际也需要一个wait阻塞或者不断循环。

相比之下多媒体定时器应该是比较好的选择,多媒体定时器本身就是一个线程。
zwjchina 2008-12-20
  • 打赏
  • 举报
回复
这问题,可能更好的方法是使用 CreateWaitableTimer
liangpei2008 2008-12-20
  • 打赏
  • 举报
回复
明白了,明白了,谢谢蒲石大哥!
刚才被Delphi封装的线程类迷惑了!
看了一下其类实现,明白了!就是要把创建Timer的过程写在CreateThread的回调函数中才能达到目的!
zwjchina 2008-12-20
  • 打赏
  • 举报
回复
to 楼上。

消息队列是以线程为基础的。

线程构造函数实际只是由主线程调用的一个过程。其代码是在主线程中运行的。
因此,在线程构造函数中创建一个Timer对象实际就是主线程创建了一个Timer对象,因此WM_TIMER消息只会进入主线程的消息队。

真正的线程执行代码只会在线程对象的Execute部分存在。

liangpei2008 2008-12-20
  • 打赏
  • 举报
回复
//请教一下僵哥,为什么在线程的构造函数中创建Timer后,当线程中有时间消息时就会把WM_TIMER投递给主线程队列呢?
//另外,僵哥,用线程周期性阻塞是不是也可以

//线程类
unit Unit2;

interface

uses
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;

interface

uses
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置为一种状态,便于在线程循环时根据该标识来将线程中止
implementation

uses 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.

faith10099 2008-12-20
  • 打赏
  • 举报
回复
3楼的代码经典
僵哥 2008-12-19
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 helodd 的回复:]
楼上的就行了, 在thread.create 的时候应创建timer对象及设置timer 的属性
[/Quote]
Thread.Create当中创建的会是在当前线程(主线程)当中执行的,在Thread.Execute当中创建的才是在该线程当中的。也就是WM_TIMER被投递的线程会是不一样的。否则的话,就不是线程当中的Timer.
helodd 2008-12-19
  • 打赏
  • 举报
回复
楼上的就行了, 在thread.create 的时候应创建timer对象及设置timer 的属性
僵哥 2008-12-18
  • 打赏
  • 举报
回复
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;
yuanscar 2008-12-18
  • 打赏
  • 举报
回复
API里面Timer相关的函数。直接可以在delphi的帮助里面查到的。
kampan 2008-12-18
  • 打赏
  • 举报
回复
重复贴,鉴定完毕!

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧