2012-03-02 5 views
5

私はこのような種類のアクションキュースレッドに取り組んでいます。特定のアクションが実行されるのを待っています。私はメインスレッドでアクションを作成し、それをキュースレッドの関数(キューの最後まで)に渡し、このアクションが実行されるのを待っています。だから、私はちょうど質問されたアクションを実行してそれを待つことを区別する必要があります。メインスレッドからワーカースレッドにイベントを渡してそれを待つのは安全ですか?

私は、次の(擬似)コードを持っていると私は

  • を知りたいのですが、それは安全なWindowsのイベントオブジェクトのスレッドで作業していますか?
  • もしそうなら、このコンセプトは効率的でしょうか?

type 
    TMyThread = class(TThread); 
    private 
    FEvent: THandle; 
    protected 
    procedure Execute; override; 
    public 
    procedure DoSomething(const AEvent: THandle); 
    end; 

procedure TMyThread.Execute; 
begin 
    // is it working with events thread safe ? 
    SetEvent(FEvent); 
    // the thread will continue, so I can't use WaitFor 
    // but it won't set this specific FEvent handle again 
    // I'm working on such kind of an action queue, so once the action with ID, 
    // here represented by the FEvent will be processed, it's removed from 
    // the action queue 
end; 

procedure TMyThread.DoSomething(const AEvent: THandle); 
begin 
    FEvent := AEvent; 
end; 

// here's roughly what I want to do 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    OnceUsedEvent: THandle; 
begin 
    // the thread is already running and it's instantiated in MyThread 
    // here I'm creating the event for the single request I need to be performed 
    // by the worker thread 
    OnceUsedEvent := CreateEvent(nil, True, False, nil); 
    try 
    // here I'm passing the event handle to the worker thread (like a kind of 
    // a request ID) 
    MyThread.DoSomething(OnceUsedEvent); 
    // and here I want to wait for 10 seconds (and also interrupt this waiting 
    // when the user closes the application if possible ?) for the thread if 
    // performs my request 
    WaitForSingleObject(OnceUsedEvent, 10000); 
    finally 
    // close the event handle 
    CloseHandle(OnceUsedEvent); 
    end; 
    // and continue with something else 
end; 

ありがとう!

+0

ボタンイベントハンドラのイベントを待っていると、メインスレッドがブロックされます。多分あなたはイベントを代わりに使うことができます(スレッドが終了するたびに呼び出されます) – jpfollenius

+2

待ち時間はあなたが望むことをするつもりはありません。中断することはできません。なぜ10代をブロックしたいのですか?それはちょっと変だ。 –

+0

理想的にはINFINITEです。それはアクションの名前を変更するためのものです。私はVirtualTreeViewノードの編集モードに入り、スレッドから名前を変更するアクションの結果を得るまでエディタを有効にしておく必要があります(名前の変更が成功した場合、終了したときに結果を渡す必要がある別のイベントハンドラがありますこのイベントハンドラは隠されています)。 –

答えて

4

はい、これは問題ありません。 CreateEventから返されたハンドルは、すべてのスレッドで自由に使用できます。それ以外のものは、これが主な用途であるため、かなり役に立たなくなるでしょう:)

+1

必ずしもそうではありません。ハンドルはスレッド固有であるか、少なくとも本質的にスレッドセーフではない可能性があります。別のスレッドが同じイベントへのアクセスを望む場合、DuplicateHandleを呼び出す必要があるか、同じイベント名でCreateEvent自体を呼び出す必要があります。 –

+0

経験的に、このハンドルは他のスレッドから使​​用できます。私はこのような方法でイベントを頻繁に使用しています。 –

+0

@RobKennedyこれはまさに私が今まで行ってきたことですが、今日まで誰かが両方のスレッドで同じハンドル変数を使用しているという例を見ていたら... –

3

GUIイベントハンドラでスレッドを待たないでください。イベント、セマフォーやmutex、sleep()ループ、DoEventsループ、またはそれらの組み合わせを待ってはいけません。

メインスレッドと通信してスレッドプールで何かが処理されたことを知らせる場合は、PostMessage()APIを参照してください。

+0

メイントレッドと通信するときに 'PostMessage'を使う代わりに1)' Thread .Queue'ここで説明されているように[同期とキューのパラメータ](http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/#more-135 )(これはFireMonkeyアプリケーションにとって便利です)、または2) 'スレッドセーフ待ち行列 'を使用して、タイマーループでメインスレッドからの待ち行列をポーリングします。 –

+0

'synchronize-and-queue-with-parameters'はOK-ishですが、実行中のスレッドを見つけるために2つのシステムコールを作成します:(タイマーを使ってポーリングすると、多くの変数の日付の値ですが、キューをポーリングするのに使用するとレイテンシが導入されます。 –

関連する問題