2009-12-02 20 views

答えて

4

スレッド上でプロシージャを実行することもできます。 OnTerminateイベントを使用して結果を取得します。確かに、.NETやC#の今日では、非同期的にメソッドを実行する簡単で便利な方法がありますが、それがDelphiで動作する方法です。

+0

私はC#jejeで何をしているのですか?今、私はdelphiに翻訳しようとしています(.NETを使いたくないので)。ありがとう。 – Sebastian

+0

私は結局、単純なBeginThreadだけで作業しました。私は実際に手続きの結果を気にしません。何かをやるかExitをしなければなりません。あなたのmsgに感謝します。 – Sebastian

16

VCLのなかにlike BeginInvoke in .NETがあるかどうかを確認するには、答えはいいえです。しかし、あなたはあなたのプログラムにリンクする小さなユニット、Andreas HausladenのAsyncCallsライブラリの形でかなり似たものを得ることができます。それはコンポーネントではないので、私はそれが適格であると思う。また、バージョン5以降のDelphiもサポートしています。非常にお勧めします。

編集:

あなたはそれが実行して取得していないので、私は例を追加します。呼び出し元コードでブロックすると、関数が返されたIAsyncCallインターフェイスポインタへの参照が保持されないという問題があります。したがって、インタフェースを実装しているオブジェクトは、一時参照が範囲外になるとすぐに破棄されます。デストラクタはVCLスレッドのコンテキストで呼び出され、WaitForSingleObject()または同様の関数を呼び出して、ワーカースレッドが終了するのを待機します。その結果、VCLスレッドがブロックされます。

あなたがインターフェイスポインタへの参照を維持場合は、正しい動作を取得します:無効にし、それはInterval非常に短くてみましょうするためにタイマーを設定し

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Timer1: TTimer; 
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    procedure Button1Click(Sender: TObject); 
    procedure Timer1Timer(Sender: TObject); 
    private 
    fAsyncCall: IAsyncCall; 
    procedure WaitForIt(ADelay: integer); 
    end; 

を、50ミリ秒と言います。ボタンをクリックすると、非同期操作が開始されます。

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Button1.Enabled := FALSE; 
    fAsyncCall := AsyncCall(WaitForIt, 1000); 
end; 

procedure TForm1.WaitForIt(ADelay: integer); 
begin 
    Sleep(ADelay); 

    EnterMainThread; 
    try 
    Randomize; 
    Color := RGB(Random(256), Random(256), Random(256)); 
    Timer1.Enabled := TRUE; 
    finally 
    LeaveMainThread; 
    end; 
end; 

この操作がアクティブな間は、他の操作は開始できません。 EnterMainThread()LeaveMainThread()を使用して、呼び出されたメソッドから直接フォームにアクセスすることも可能である方法

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    Timer1.Enabled := FALSE; 
    Assert((fAsyncCall <> nil) and fAsyncCall.Finished); 
    fAsyncCall := nil; 
    Button1.Enabled := TRUE; 
end; 

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
    CanClose := (fAsyncCall = nil) or fAsyncCall.Finished; 
end; 

注完了時に、それは、フォームに通知し、インタフェースリファレンスをリセットするタイマーを可能にします。

上記のコードは絶対的な最小値ではなく、いくつかのアイデアを示すことを目的としています。

+0

私はそのライブラリを昨日見ましたが、私はコードを最小限に抑えたかったので、とにかくそれを使用することになります。それは単純な.pas単位の権利ですか? – Sebastian

+0

はい、それは2〜3のkLOCの間でしかありませんので、既にごくわずかです。私はこれが勝てるとは思わない。インターフェイスは非常に簡単です。全ての毛深いものは 'implementation'部分にあります;-)呼び出しが終了するまで' IAsyncCall'参照を保持してください。そうしないと、最後の参照カウントの減少がブロックされます。 – mghie

+0

これは最高の解決策になるようです。どうもありがとうございます。 – Sebastian

関連する問題