1

優れたOmniThreadLibraryライブラリを使用して、スレッド化されたソースコードの解析を実装します。プログラムは、既存の解析を破棄し、ソースコードが変更されるたびに解析を再開する必要があります。

以下に示すコードスニペットを使用してこれを行いますが、正しい方法ですか?関数Terminated内のスレッドのプロパティを確認する必要がありますか?ThreadedParseHtml

if FParserThread <> nil then
begin
  FParserThread.RemoveMonitor;
  FParserThread.Terminate(500);
end;

FParserThread := CreateTask(ThreadedParse);
FParserThread.SetParameter('SourceCode', Editor.Lines.Text);
FParserThread.MonitorWith(FParserThreadMonitor);
FParserThread.Run;

前もって感謝します!

編集1FParserThread :この質問を再度開いて申し訳ありませんが、十分な時間をかけてメソッドを呼び出して、それ自体で完了しないとメモリリークが発生することがわかりましTerminateた...メモリリークの原因について何か考えはありますか?ありがとう!

編集2 :このブログ投稿を読んでくださいThreadedParse。コードのすべてのステップの後で問題が発生した場合Terminatedは中断するため、問題が何であるかはまだわかりません。

編集3:ロブの質問に答える:

  1. OnTerminatedイベントハンドラー(ここには表示されていません)では、FParserThreadは「nil」に設定されているため、「FParserはそれ自体で完了します」とは、if FParserThread <> nil thenブロックが実行されないことを意味します。この場合、FParserThreadは、解析が完了したために終了します。

  2. コードの背後にあるロジックは、これがコードエディターであり、コードを編集すると、新しいコード編集が発生したが前の解析が行われた場合に、ソースコードを内部ツリープレゼンテーションに解析するためのスレッドが開始されるというものです。編集されていない場合、プログラムは最初に前の解析スレッドを強制的に開始し、次に新しい解析スレッドを開始します。これはおそらく良いアプローチではありません...

編集4 :この同様のSO質問を読んだ後、パラメーターなしで呼び出すようにコードを変更しましFParserThread.Terminateた。つまり、正しく理解していれば、そのステートメントはスレッドに終了を通知するだけであり、実際のスレッドタスク内でロジックを適用しました。Terminatedプロパティが。の場合は、スレッドの実行を終了しますTrue

これで、 Tracetoolの助けを借りて、イベント(メモリをクリーンアップする場所)を呼び出しFParserThread.Terminateた後OnTaskMessage、再度起動されないことがわかりました。これがメモリリークの原因でした。

4

2 に答える 2

4

Terminated関連するタスクでプロパティを確認する必要はありません。を呼び出しTerminate(1)ています。指定した1ミリ秒のウィンドウ内でスレッドが終了しない場合、スレッドは強制的に強制終了されます。

ただし、スレッドを強制的に強制終了することは実際には良い考えではありません。そのスレッドは、強制終了したときにミューテックスまたはクリティカルセクションを持っていた可能性があるため、強制終了すると、共有データが不整合な状態のままになります。これは、プログラム全体に悪影響を与える可能性があります。

スレッドを終了することをスレッドに通知することをお勧めしますが、より現実的な終了期限を指定してください。他のスレッド内では、スレッドが終了するように要求されているかどうかを時々確認してから、スレッドを正常に終了させる必要があります。

スレッドが指定された制限時間内に終了しない場合は、より大きな問題が発生し、強制的に強制終了しても解決されません。

于 2012-03-29T20:22:29.327 に答える
2

ここでのOP、OmniThreadLibraryを2年以上使用した後、私の結論は、OTLタスクを停止する適切な方法はキャンセルトークンを使用することです。以下のコード例。

呼び出し元のスレッド(通常はメインスレッド)で、次の呼び出しを行います。

//this will tell (not kill) the thread identified by myTask to stop.
myTask.CancellationToken.Signal;

呼び出し先スレッドでは、task.CancellationToken.IsSignaledプロパティを定期的にチェックする必要があります。それがtrueになると、実行を終了し、スレッドの終了はシステムとOTLによって処理されます。

if task.CancellationToken.IsSignaled then
  Exit;
于 2014-06-10T06:32:08.453 に答える