如何在Delphi中编写Debounce()过程?
我想编写一个类似于Javascript中常用实现的去盎司过程。例如, 我想可能是这样的:如何在Delphi中编写Debounce()过程?,delphi,anonymous-methods,Delphi,Anonymous Methods,我想编写一个类似于Javascript中常用实现的去盎司过程。例如, 我想可能是这样的: procedure Debounce(const TimeMS : integer; MyAnonymousProcedure : TProc); function Debounce(Delay: TDateTime; Proc: TProc): TProc; var LastCall: TDateTime; begin LastCall := 0; Result := procedure
procedure Debounce(const TimeMS : integer; MyAnonymousProcedure : TProc);
function Debounce(Delay: TDateTime; Proc: TProc): TProc;
var
LastCall: TDateTime;
begin
LastCall := 0;
Result := procedure
begin
if LastCall + Delay <= Now then
Proc;
LastCall := Now;
end;
end;
可以像这样使用:
begin
Debounce(200, procedure
begin
//Do something here...
end);
end;
可能的实施#1
Debounce()过程将检查调用目标方法以来的时间。如果在X时间内调用了目标方法,则该方法调用将被延迟
伪代码版本:
procedure Debounce(const TimeMS : integer; MyAnonymousProcedure : TProc);
var
TimeSinceCalled : integer;
begin
TimeSinceCalled := FindTimeSinceProcedureLastCalled(MyAnonymousProcedure);
if TimeMS < TimeSinceCalled then
begin
// The procedure hasn't been called recently,
SaveTimeOfProcedureCall(MyAnonymousProcedure); // so save the current time...
MyAnonymousProcedure; // ...and call the procedure.
end else
begin
// The procedure has been called recently so we use a timer
// to call the procedure in X milliseconds.
// The timer is reset each time Debounce() is called
// so procedures will only be called when the Debounce time-out has
// be passed.
GlobalTimer.Reset;
GlobalTimer.CallProcedureIn(MyAnonymousProcedure, TimeMS);
end;
end;
procedure-Debounce(const-TimeMS:integer;MyAnonymousProcedure:TProc);
变量
调用时间:整数;
开始
TimeSinceCalled:=FindTimesinceProceducedRelastCalled(MyAnonymousProcedure);
如果调用TimeMS
我面临的问题是我需要一些方法来确定目标程序。我的第一个想法是使用目标过程的方法地址作为ID。例如:ID:=地址(Foo)代码>ID:=Addr(Foo)代码>
但这不适用于匿名方法,因为它们在我的测试中使用相同的地址。理想情况下,应该自动生成ID。有什么想法吗 您说所有匿名过程的地址都是相同的,但这是不可能的。相反,我怀疑您尝试了错误的值。你说你调用地址
,但是没有这样的功能。您可能指的是Addr
,它与@
运算符相同。但是,这将为您提供MyAnonymousProcedure
形式参数的地址,而不是其中存储的地址。很可能每次调用函数时,参数都有相同的地址
您正在寻找一种识别不同过程引用的方法。引用本身就足够了。您可以使用t字典
将过程映射到它们的上次调用时间
危险在于,每次运行时,使用过程文字调用Debounce
函数时,可能最终构造该过程对象的全新实例,因此其地址将不同于以前构造的任何过程,即使它使用相同的代码和相同的捕获变量值
JavaScript版本也容易出现同样的问题,这就是为什么它根本不尝试识别函数的原因。相反,它返回一个新函数,该函数封装传入的函数。新函数添加了延迟行为。在Delphi中,它可以像这样工作:
procedure Debounce(const TimeMS : integer; MyAnonymousProcedure : TProc);
function Debounce(Delay: TDateTime; Proc: TProc): TProc;
var
LastCall: TDateTime;
begin
LastCall := 0;
Result := procedure
begin
if LastCall + Delay <= Now then
Proc;
LastCall := Now;
end;
end;
函数去抖动(延迟:TDateTime;过程:TProc):TProc;
变量
LastCall:TDateTime;
开始
上次调用:=0;
结果:=程序
开始
如果LastCall+Delay我尝试使用TDictionary
,但是Dictionary.Contains(aProc)
函数在看起来不应该返回false时总是返回false。我用一个整数作为字典键测试了我的代码,它工作得很好,所以我不确定那里发生了什么。如果不使用Addr()或@functions,我如何获得MyAnonymousProcedure
引用的例程的地址?我喜欢你的Debounce()实现。它非常简洁。然而,我希望避免在调用位置维护对某个例程的非公告版本的引用。因此,尝试根据匿名方法输入自动创建某种类型的ID。正如我所说的,每次使用过程文本调用函数时(即编写procedure begin…end
),都会使用新标识创建一个新过程,因此字典正确地报告尚未看到该实例。将引用存储在变量中,然后测试变量是否存在。您将其与JavaScript进行比较,并且在该语言中,您需要存储debounce
函数的结果;在德尔福也不会有什么不同。