gpt4 book ai didi

delphi - 在运行时创建并运行 TTimer

转载 作者:行者123 更新时间:2023-11-29 17:46:04 26 4
gpt4 key购买 nike

我试图在 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 Error] unit1.pas(2153): E2010 Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'"

有什么提示吗?

最佳答案

TNotifyEvent 声明为:

TNotifyEvent = procedure(Sender: TObject) of object;

of object 使它成为一个closure,这是一种特殊类型的方法指针,带有2个指针——一个指向对象的指针,一个指向非对象的指针- 在对象上调用的静态类方法。因此,您不能将独立函数(当然也不能是嵌套函数)直接分配给 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 及更高版本中,您可以使用 class helper :

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;

关于delphi - 在运行时创建并运行 TTimer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49637129/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com