如何使一个等待中的定时器得到信号? 本帖最后由 ljdzxx 于 2011-03-08 13:31:54 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 procedure TForm1.FormDestroy(Sender: TObject);begin CloseHandle(hTimerEvent);end; execute代码里加上FreeOnTerminate := True; 从你的代码中看,如果你直接CloseHandle(hTimerEvent)则你的线程就会进入死循环做如下更改: case WaitForSingleObject(hTimerEvent,INFINITE) of WAIT_OBJECT_0: ;//干活; WAIT_TIMEOUT, WAIT_FAILED: Break; end;这样你CloseHandle(hTimerEvent)就会正常退出 试了还是不行,我知道什么原因了:我把CloseHandle放在线程的析构函数中执行,这样当我的主程序Free所有线程的时候就会执行了,但问题关键是:CloseHandle函数如果在调用WaitForSingleObject之前执行,那么WaitForSingleObject是会立即返回WAIT_FAILED的,可以正常退出,但现实情况是:N多线程都已经执行到WaitForSingleObject这句了并被这句代码阻塞,那么你再CloseHandle是无济于事的,WaitForSingleObject函数不会立即返回WAIT_FAILED,而是仍然要等够了设定的时间,才返回WAIT_OBJECT_0 说错了,我把CloseHandle放在“主窗体”的析构函数中执行,不是线程procedure TForm1.Destroy;beginCloseHandle(hTimerEvent);FreeAllThread; //逐个释放所有线程end; TThread的析构函数我看了,他先要检查线程中的工作是否已完成,没有完成的话要继续等它做完,然后才逐步释放资源。 unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;type TMyThread = class(TThread) FSite: integer; protected procedure Execute; override; public Constructor Create(CreateSuspended: Boolean); property Site : integer read FSite write FSite; end;type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } t: integer; end;var Form1: TForm1;implementation{$R *.dfm}var hTimerEvent: THandle; lpDueTime: Int64; //ÑÓ³Ù lPeriod: Integer; //ÖÜÆÚ lpTimerName: PChar;constructor TMyThread.Create(CreateSuspended: Boolean);begin inherited Create(true);end;procedure TMyThread.Execute;var i: Integer;begin FreeOnTerminate := True; for i := 0 to 500000 do begin if WaitForSingleObject(hTimerEvent, INFINITE) = WAIT_OBJECT_0 then begin Form1.Canvas.Lock; Form1.Canvas.TextOut(10, FSite*20, IntToStr(i)); Form1.Canvas.Unlock; end; end;end;procedure TForm1.FormCreate(Sender: TObject);begin t:= 1; lpTimerName := PChar('Knowing'+IntToStr(Handle)); //¶¨Ê±Äں˶ÔÏóÃû lPeriod := 100; //ÖÜÆÚ lpDueTime := 0-1*100*10000; //0-lPeriod*10000;//¸ºÊýΪÏà¶Ôʱ¼ä:¶¨Ê±Æ÷ºÎʱ¿ªÊ¼ÓÐÐźţ¬Õâ¸ö²ÎÊýÄܾ«È·µ½100ÄÉÃë hTimerEvent := CreateWaitableTimer(nil, False, lpTimerName); //µÚ¶þ¸ö²ÎÊýΪÊÇ·ñÊÖ¶¯ÖØÖà SetWaitableTimer(hTimerEvent, lpDueTime, lPeriod, nil, nil, False);end;procedure TForm1.Button1Click(Sender: TObject);var mt: TMyThread;begin mt:= TMyThread.Create(true); // 多按几次 button mt.FSite:= t; mt.Resume; inc(t);end;procedure TForm1.FormDestroy(Sender: TObject);begin CloseHandle(hTimerEvent);end;end. 你的lPeriod := 100; 100是毫秒,设置过短测试不到效果的,你设置60秒试试,肯定要等N久才会退出! 我已经解决了,方法是窗体析构的时候,重新执行SetWaitableTimer,并设置一个极短的时间。 忘说了,你并没有在主程序退出的时候手动去释放这些线程,而是在线程里设置FreeOnTerminate := True;,你是想让线程自己释放,这样会有个问题:当你的主程序还没释放的时候这样做是没问题的,一旦你的主程序都退出了,如果你的线程里还有工作没昨晚,那你就惨了,你的线程在内存里会像没主人的孩子那样乱搞,一不小心就报Read Address 0x0000000XX 错误。 关于发布软件时,兼容系统的问题. 拷贝一个excel的内容,存为图片,保存到word中 怎样写下列问题的SQL语句? 求DELPHI的正则表达式单元 interbase数据库的问题,回答了我给100分? 怎么样把TColorDialog的后值保存起来?? 请教三个关于在sql语句中对字段做类型转换的问题---分全给了 在线等待:我忘了insert语句的语法,请明示(SQL语句) 关于dbchart的一个问题 txtextcontrol控件加水印、存数据库问题 Delphi6.0调用Oracle的存储过程的结果和PL/SQL里面Test存储过程的结果不一致 关于DBGRIDEH的行、列顺序号
begin
CloseHandle(hTimerEvent);
end;
CloseHandle(hTimerEvent)
则你的线程就会进入死循环
做如下更改:
case WaitForSingleObject(hTimerEvent,INFINITE) of
WAIT_OBJECT_0: ;//干活;
WAIT_TIMEOUT, WAIT_FAILED: Break;
end;这样你
CloseHandle(hTimerEvent)
就会正常退出
beginCloseHandle(hTimerEvent);
FreeAllThread; //逐个释放所有线程end;
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;type
TMyThread = class(TThread)
FSite: integer;
protected
procedure Execute; override;
public
Constructor Create(CreateSuspended: Boolean);
property Site : integer read FSite write FSite;
end;type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
t: integer;
end;var
Form1: TForm1;implementation{$R *.dfm}var
hTimerEvent: THandle; lpDueTime: Int64; //ÑÓ³Ù
lPeriod: Integer; //ÖÜÆÚ
lpTimerName: PChar;constructor TMyThread.Create(CreateSuspended: Boolean);
begin
inherited Create(true);
end;procedure TMyThread.Execute;
var
i: Integer;
begin
FreeOnTerminate := True;
for i := 0 to 500000 do
begin
if WaitForSingleObject(hTimerEvent, INFINITE) = WAIT_OBJECT_0 then
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(10, FSite*20, IntToStr(i));
Form1.Canvas.Unlock;
end;
end;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
t:= 1;
lpTimerName := PChar('Knowing'+IntToStr(Handle)); //¶¨Ê±Äں˶ÔÏóÃû
lPeriod := 100; //ÖÜÆÚ
lpDueTime := 0-1*100*10000; //0-lPeriod*10000;//¸ºÊýΪÏà¶Ôʱ¼ä:¶¨Ê±Æ÷ºÎʱ¿ªÊ¼ÓÐÐźţ¬Õâ¸ö²ÎÊýÄܾ«È·µ½100ÄÉÃë
hTimerEvent := CreateWaitableTimer(nil, False, lpTimerName); //µÚ¶þ¸ö²ÎÊýΪÊÇ·ñÊÖ¶¯ÖØÖÃ
SetWaitableTimer(hTimerEvent, lpDueTime, lPeriod, nil, nil, False);
end;procedure TForm1.Button1Click(Sender: TObject);
var
mt: TMyThread;
begin
mt:= TMyThread.Create(true); // 多按几次 button
mt.FSite:= t;
mt.Resume;
inc(t);
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hTimerEvent);
end;end.