1


4

私はDelphiで特定のレジストリの変更を監視する方法を探していました。 about.comで solutionを見つけました:

procedure TRegMonitorThread.Execute; InitThreadを開始します。 //終了されずにここで省略されたメソッドは、WaitForSingleObject(FEvent、INFINITE)= WAIT_OBJECT_0で開始され、その後開始されます。fChangeData.RootKey:= RootKey; fChangeData.Key:=キー。 SendMessage(Wnd、WM_REGCHANGE、RootKey、LongInt(PChar(Key))); ResetEvent(FEvent);

RegNotifyChangeKeyValue(FReg.CurrentKey、1、Filter、FEvent、1);終わり;終わり;終わり;

私のアプリケーションでは、このスレッドをオンデマンドで起動および停止する必要がありますが、上記のコードでは許可されていません。 Terminatedフラグを設定しただけではうまくいきません。

何らかの理由でスレッドに待機を停止してから解放し、必要に応じて新しいスレッドを作成するように指示すれば十分です。 それを達成するためにどのように私はこのコードを変えることができますか?

3 Answer


8


WaitForSingleObject()`の代わりに `WaitForMultipleObjects()`を2つのイベントの配列と共に使用してください。 手動リセットイベントをスレッドクラスに追加し、 `Terminated`を True`に設定した後にそれを知らせてください。 2つのイベントのうちどちらが通知されたのかの戻り値を確認し、それに応じて対処します。

編集:

アイデアを実証するためのいくつかの最小限のDelphi 2009コード。 使用単位のリストに `SyncObjs`を追加して、

fTerminateEvent:TEvent。

あなたのスレッドクラスの `private`セクションに。

コンストラクタTTestThread.Create;継承されたCreateの開始(TRUE)。 fTerminateEvent:= TEvent.Create(nil、True、False、 ''); // ... 履歴書;終わり;

デストラクタTTestThread.Destroy; fTerminateEvent.SetEventを開始します。終了します。 //コード内でTerminatedをチェックしない場合は必要ありませんWaitFor; fTerminateEvent.Free;継承されました;終わり;

プロシージャTTestThread.Execute; varハンドル:THandleの配列[0..1]。ハンドル[0]:= ...を開始します。 //イベントハンドルはここに移動します。Handles [1]:= fTerminateEvent.Handle; WaitForMultipleObjects(2、@Handles [0]、False、INFINITE)<> WAIT_OBJECT_0の場合は終了せずに終了します。 // ... 終わり;終わり;

あなたはそれにあなたの質問の中のコードを追加するだけでよいです。 スレッドインスタンスを解放しようとするだけで、必要に応じてスレッドのブロックを解除するために必要なすべてのことが実行されます。


1


代わりにINFINITEでは、WaitForSingleObjectを一定期間後にタイムアウトさせる必要があります。 そのようにしてループは続き、Terminatedがチェックされます。

procedure TRegMonitorThread.Execute; InitThreadを開始します。 //終了されずにここで省略されたメソッドは、WaitForSingleObject(FEvent、1000)= WAIT_OBJECT_0で開始してから開始するfChangeData.RootKey:= RootKey; fChangeData.Key:=キー。 SendMessage(Wnd、WM_REGCHANGE、RootKey、LongInt(PChar(Key))); ResetEvent(FEvent);

RegNotifyChangeKeyValue(FReg.CurrentKey、1、Filter、FEvent、1);終わり;終わり;終わり;

TThread.SuspendメソッドとTThread.Resumeメソッドは理論的にはスレッドを一時的に停止するために使用できますが、Delphi 2010では現在では安全ではないと認識しています。 https://stackoverflow.com/questions/1418333/tthread-resume-is-deprecated-in-delphi-2010-what-should-be-used-in-placeを参照してください。TThread.resumeはDelphi-2010では推奨されません。代わりに使用できますか。]およびhttp://msdn.microsoft.com/en-us/library/ms686345%28VS.85%29.aspx


1


これはうまくいきます。下記のようにちょっとした変更を加えてください。

TRegMonitorThread = class(TThread)... 公開手続き終了再導入する。
...

プロシージャTRegMonitorThread。 終了します。 //新しいパブリックプロシージャを追加します。 Windows.SetEvent(FEvent);終わり;

procedure TRegMonitorThread.Execute; InitThreadを開始します。

WaitForSingleObject(FEvent、INFINITE)= WAIT_OBJECT_0であれば終了しないで開始し、終了した場合は開始し、// < - この2行を追加終了; ... 終わり;終わり;終わり;