我正试图在Delphi中实现类似于Javascript的setTimeout()过程的行为:在延迟几秒钟后运行。为此,我在运行时创建一个TTimer,运行它,然后释放它。
这是我的代码:
procedure createAndRunTimer();
procedure goTimer(Sender: TObject);
begin
(sender as ttimer).enabled := false;
// do stuff here
sender.free;
end;
var
t : TTimer;
begin
t := TTimer.Create(frmprinc);
t.Interval := 5000;
t.OnTimer := goTimer(t);
end;但是我的代码无法编译,编译器将返回以下错误:
DCC错误单元1.PAS(2153):E2010不兼容类型:“TNotifyEvent”和“过程、非类型化指针或非类型化参数”
有什么暗示吗?
发布于 2018-04-03 19:18:05
TNotifyEvent声明为:
TNotifyEvent = procedure(Sender: TObject) of object;of object使其成为一个闭包,它是一种特殊类型的方法指针,包含两个指针--一个指向对象的指针,以及一个指向在对象上调用的非静态类方法的指针。因此,不能直接将独立函数(当然不是嵌套函数)分配给TNotifyEvent。这正是编译器所抱怨的。
因此,您需要声明一个类来包装OnTimer事件处理程序,例如:
type
TTimerEvents = class
public
procedure goTimer(Sender: TObject);
end;
procedure TTimerEvents.goTimer(Sender: TObject);
begin
(Sender as TTimer).Enabled := false;
// do stuff here
// NOTE: you cannot destroy the Sender object from here, you must delay
// the destruction until after this handler exits! You can post a
// custom window message via PostMessage() and have the message handler
// call Sender.Free(). Or, you can use a worker thread to call
// Sender.Free() via TThread.Synchronize() (or TThread.Queue() in Delphi
// 8 and later). Or, in Delphi 10.2 Tokyo and later, you can call
// Sender.Free() via TThread.ForceQueue(). Or, use whatever other
// mechanism you want to use to call Sender.Free(), as long as it works
// asynchronously and calls Sender.Free() in the same thread that
// constructed the TTimer object ...
end;
var
events: TTimerEvents;
procedure createAndRunTimer();
var
t : TTimer;
begin
t := TTimer.Create(frmprinc);
t.Interval := 5000;
t.OnTimer := events.goTimer;
t.Enabled := True;
end;
initialization
events := TTimerEvents.Create;
finalization
events.Free;或者,您可以使用class方法,这样就不需要包装类的实际实例:
type
TTimerEvents = class
public
class procedure goTimer(Sender: TObject);
end;
class procedure TTimerEvents.goTimer(Sender: TObject);
begin
(Sender as TTimer).Enabled := false;
// do stuff here
// delay-destroy the Sender as needed ...
end;
procedure createAndRunTimer();
var
t : TTimer;
begin
t := TTimer.Create(frmprinc);
t.Interval := 5000;
t.OnTimer := TTimerEvents.goTimer;
t.Enabled := True;
end;或者,在Delphi 2006及更高版本中,您可以使用类帮助者
type
TTimerHelper = class helper for TTimer
public
procedure goTimer(Sender: TObject);
end;
procedure TTimerHelper.goTimer(Sender: TObject);
begin
(Sender as TTimer).Enabled := false;
// do stuff here
// delay-destroy the Sender as needed ...
end;
procedure createAndRunTimer();
var
t : TTimer;
begin
t := TTimer.Create(frmprinc);
t.Interval := 5000;
t.OnTimer := t.goTimer;
t.Enabled := True;
end;尽管如此,还是有一种方法可以使用独立函数,而无需使用任何类包装器:
procedure goTimer(Self: Pointer; Sender: TObject);
begin
(Sender as TTimer).Enabled := false;
// do stuff here
// delay-destroy the Sender as needed ...
end;
procedure createAndRunTimer();
var
t : TTimer;
event : TNotifyEvent;
begin
t := TTimer.Create(frmprinc);
t.Interval := 5000;
TMethod(event).Data := nil; // or whatever you want to pass to the Self parameter...
TMethod(event).Code := @goTimer;
t.OnTimer := event;
t.Enabled := True;
end;发布于 2018-04-03 19:24:03
我使用Torry的这个过程作为延迟,它不会在执行时锁定线程:
procedure Delay(dwMilliseconds: Longint);
var
iStart, iStop: DWORD;
begin
iStart := GetTickCount;
repeat
iStop := GetTickCount;
Application.ProcessMessages;
Sleep(1);
until (iStop - iStart) >= dwMilliseconds;
end;https://stackoverflow.com/questions/49637129
复制相似问题