3

開始された単純な TTimer に問題があり、その OnTimer イベントがメイン アプリ スレッドで実行されます。コードは次のようになります。

procedure TForm1.DoSomeStuff();
begin
     OmniLock.Acquire;
     try
        Parallel.Pipeline.NumTasks(MaxThreads).Stage(StageProc).Run;

        if (MyTimer = nil) then
        begin
             MyTimer := TTimer.Create(nil);
             MyTimer.Interval := 60 * 1000;  // timer fired every 60 seconds
             MyTimer.OnTimer := MyTimerEvent;
             MyTimer.Enabled := True;
         end;
      finally
             OmniLock.Release;
      end;    // try/finally
 end;

単純なプロジェクト/デモでコードを実行すると、すべてが正常に機能しますが、私のアプリ (Omni Thread Library v3 を使用) では、タイマー イベントが発生しません。

私はそれが何もないと確信しています、私は何が間違っているのか理解できません!

私は三重にチェックしました:MyTimerコードで一度だけ割り当てられ、そのOnTimerイベントが正しく割り当てられているなど...

Delphi 2010 を使用しています

誰でもこれを修正する方法を知っていますか?

4

1 に答える 1

7

TTimerメッセージベースのタイマーです。がそのメッセージを処理TTimerするためには、 が作成されるスレッド コンテキストにアクティブなメッセージ ループが必要です。TTimerWM_TIMER

TTimerスレッドセーフなタイマーではありません。メッセージを受信するには、それ自体にウィンドウ ハンドルWM_TIMERを割り当てる必要があります。HWNDこれは VCL のAllocateHWnd()関数を使用して行われますが、これはスレッド セーフではなく、メイン スレッドのコンテキスト外から呼び出すことはできません。

スレッド セーフ タイマーが必要な場合は、直接呼び出してメッセージを直接CreateWindow()ポンプ/処理するか、 または を介し​​たスレッド化されたマルチメディア タイマーや、またはを介し​​た単純なビジー ループWM_TIMERなど、別のタイマー メカニズムを使用します。タイマーを何に使用しているかを知らなければ、ニーズに合った代替手段を特定することは困難です。timeSetEvent()Sleep()WaitForSingleObject()

于 2012-05-14T19:54:36.550 に答える