delphi中的提供了一個tthread的多線程類,開發(fā)者可以根據(jù)自身的需要,定制相應(yīng)功能的多線程,而定時器在多線程中有很廣泛的應(yīng)用,在這里,只說關(guān)于waitforsingleobject來做定時器的一些關(guān)鍵問題。(關(guān)于定時器的相關(guān)知識,請閱讀《深度歷險》)
waitforsingleobject是一個api函數(shù),采用該函數(shù),需要調(diào)用createevent,timesetevent,然后才能使用。但是這里使用到的event在線程中聲明的位置不一樣,效果也不一樣,以下給出兩種聲明方式:
unit PTUnit;
interface
uses
Classes,mmsystem, Windows, sysutils,
Forms;
type
TPingThread = class(TThread)
private
{ Private
declarations }
{將event聲明為該線程類的私有數(shù)據(jù)成員}
timerid:integer;
htimerevent:Thandle;
fFileName:
string;
protected
procedure
Execute; override;
public
constructor
create;
procedure
SetOver;
published
end;
implementation
constructor TPingThread.Create;
begin
FreeOnTerminate := true;
Inherited Create(true);
end;
procedure TPingThread.SetOver;
begin
timerid :=
timesetevent(5,0,TFNTimecallback(htimerevent),0,time_periodic or
time_callback_event_set);
end;
procedure TPingThread.Execute;
begin
htimerevent := CreateEvent(nil, False, False,
nil);
timerid :=
timesetevent(5*1000,0,TFNTimecallback(htimerevent),0,time_periodic
or time_callback_event_set);
repeat
if
WaitForSingleObject(htimerevent,INFINITE) = WAIT_OBJECT_0
then
begin
if Terminated then break;
dosomething;
end;
until false;
timekillevent(timerid);
CloseHandle(htimerevent);
end;
end.
這種聲明方式保證了線程能夠正常的執(zhí)行。但是,下面一種聲明方式就不行了,當(dāng)你只是創(chuàng)建一個線程實例的時候,還能正常的執(zhí)行,如果創(chuàng)建了兩個以上的線程實例,那就不對了。
unit PTUnit;
interface
uses
Classes,mmsystem, Windows, sysutils,
Forms;
type
TPingThread = class(TThread)
private
{ Private
declarations }
fFileName:
string;
protected
procedure
Execute; override;
public
constructor
create;
procedure
SetOver;
published
end;
implementation
{在實現(xiàn)部分聲明事件}
var
timerid:integer;
htimerevent:Thandle;
constructor TPingThread.Create;
begin
FreeOnTerminate := true;
Inherited Create(true);
end;
procedure TPingThread.SetOver;
begin
timerid :=
timesetevent(5,0,TFNTimecallback(htimerevent),0,time_periodic or
time_callback_event_set);
end;
procedure TPingThread.Execute;
begin
htimerevent := CreateEvent(nil, False, False,
nil);
timerid :=
timesetevent(5*1000,0,TFNTimecallback(htimerevent),0,time_periodic
or time_callback_event_set);
repeat
if
WaitForSingleObject(htimerevent,INFINITE) = WAIT_OBJECT_0
then
begin
if Terminated then break;
dosomething;
end;
until false;
timekillevent(timerid);
CloseHandle(htimerevent);
end;
end.
以上兩個除了事件聲明位置不一樣,其他功能均一樣的代碼在創(chuàng)建了兩個以上線程實例的時候,第一個能夠正常執(zhí)行,第二個中的定時器的時間間隔就會出問題,而且當(dāng)結(jié)束其中一個線程的時候,另外一個線程也無法正常工作。
總結(jié):建議使用第一種聲明方式,這種方式能確保正常運行。
|