はsetTimeout
JavaScript 言語で役立ちます。Delphi でこの関数をどのように作成しますか?
SetTimeOut(procedure (Sender: TObject);
begin
Self.Counter := Self.Counter + 1;
end, 200);
はsetTimeout
JavaScript 言語で役立ちます。Delphi でこの関数をどのように作成しますか?
SetTimeOut(procedure (Sender: TObject);
begin
Self.Counter := Self.Counter + 1;
end, 200);
TTimer
をそのままにして、SetTimer
関数を使用し、そのコールバック関数を使用することができると思います。タイマー ID とその (匿名の) メソッドを何らかのコレクションに格納する必要があります。Delphi のバージョンについて言及していないので、単純なクラスをTObjectList
コレクションとして使用しました。
原則は簡単です。SetTimer
コールバック関数を指定して関数を呼び出し、匿名メソッドを使用して新しくインスタンス化されたシステム タイマー ID をコレクションに格納するだけです。そのコールバック関数が実行されたら、ID でコレクション内のそのコールバックを引き起こしたタイマーを見つけ、それを強制終了し、匿名メソッドを実行して、コレクションから削除します。サンプルコードは次のとおりです。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Contnrs;
type
TOnTimerProc = reference to procedure;
TOneShotTimer = class
ID: UINT_PTR;
Proc: TOnTimerProc;
end;
procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal);
type
TForm1 = class(TForm)
Timer1: TTimer;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
TimerList: TObjectList;
implementation
{$R *.dfm}
procedure TimerProc(hwnd: HWND; uMsg: UINT; idEvent: UINT_PTR;
dwTime: DWORD); stdcall;
var
I: Integer;
Timer: TOneShotTimer;
begin
for I := 0 to TimerList.Count - 1 do
begin
Timer := TOneShotTimer(TimerList[I]);
if Timer.ID = idEvent then
begin
KillTimer(0, idEvent);
Timer.Proc();
TimerList.Delete(I);
Break;
end;
end;
end;
procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal);
var
Timer: TOneShotTimer;
begin
Timer := TOneShotTimer.Create;
Timer.ID := SetTimer(0, 0, ATimeout, @TimerProc);
Timer.Proc := AProc;
TimerList.Add(Timer);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetTimeout(procedure
begin
ShowMessage('OnTimer');
end,
1000
);
end;
initialization
TimerList := TObjectList.Create;
TimerList.OwnsObjects := True;
finalization
TimerList.Free;
end.
簡易版 (Delphi 2009 以降):
@Davidのコメントで示唆されているように、これは上記と同じコードですが、ジェネリック辞書を使用した別のユニットにあります。このユニットの の使用法はSetTimeout
、上記のコードと同じです。
unit OneShotTimer;
interface
uses
Windows, Generics.Collections;
type
TOnTimerProc = reference to procedure;
procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal);
var
TimerList: TDictionary<UINT_PTR, TOnTimerProc>;
implementation
procedure TimerProc(hwnd: HWND; uMsg: UINT; idEvent: UINT_PTR;
dwTime: DWORD); stdcall;
var
Proc: TOnTimerProc;
begin
if TimerList.TryGetValue(idEvent, Proc) then
try
KillTimer(0, idEvent);
Proc();
finally
TimerList.Remove(idEvent);
end;
end;
procedure SetTimeout(AProc: TOnTimerProc; ATimeout: Cardinal);
begin
TimerList.Add(SetTimer(0, 0, ATimeout, @TimerProc), AProc);
end;
initialization
TimerList := TDictionary<UINT_PTR, TOnTimerProc>.Create;
finalization
TimerList.Free;
end.
何かのようなもの
type
TMyProc = Procedure of Object(Sender: TObject);
TMyClass = Object
HandlerList = TStringList;
TimerList = TStringlist;
Procedure CallThisFunction(Sender :TObject);
function setTimeout(Timeout: Integer; ProcToCall : TMyProc)
end;
function setTimeout(Timeout: Integer; ProcToCall : TMyProc)
var
Timer : TTimer;
begin
Timer := TTimer.Create(nil);
Timer.OnTimer := CallOnTimer;
Timer.Interval := Timeout;
Timer.Enabled := true;
HandlerList.AddObject(ProcToCall);
TimerList.AddObject(ProcToCall);
end;
function CallOnTimer(Sender : TObject)
var TimerIndex : Integer;
HandlerToCall : TMyProc;
Timer : TTimer;
begin
TimerIndex := TimerList.IndexOfObject(Sender);
HandlerToCall := (HandlerList.Objects[TimerIndex] as TMyProc) ;
HandlerToCall(Self);
HandlerList.Delete(TimerIndex);
Timer := (TimerList.Objects(TimerIndex) as TTimer);
Timer.Free;
TimerList.Delete(TimerIndex);
end;
これは一緒にハッキングされたばかりで、まったくテストされていませんが、概念を示しています。基本的に、呼び出したいタイマーとプロシージャーのリストを作成します。自己オブジェクトは呼び出されたときにプロシージャに渡されますが、setTimeout の呼び出しでパラメータとして使用されるオブジェクトを含む 3 番目のリストを作成できます。
オブジェクトは、メソッドが呼び出された後に解放することによってクリーンアップされます。
javascripts setTimeout とまったく同じではありませんが、デルファイ近似です。
ps。私は Delphi 7 から実際に移行したわけではないので、Delphi XE でこれを行うための新しい方法があれば、私はそれについて知りません。
関数が毎秒 5 回ではなく 1 回呼び出されると仮定すると、次のようになります。
Parallel.Async(
procedure; begin
Sleep(200);
Self.Counter:=Self.Counter+1; end; );
あなたが受け入れたもののような、より複雑なソリューションがあり、タイマー アクションに名前付きオブジェクトを使用し、SetTimer メソッドを使用します。http://code.google.com/p/omnithreadlibrary/source/browse/trunk/tests/17_MsgWait/test_17_MsgWait.pasのよう に、以前のバージョンには匿名関数で SetTimer がありましたが、現在はなくなりました。
ただし、あなたが求めた単純な匿名閉鎖アプローチの場合、おそらく Wait(xxX) が適しています。