4

マルチスレッドアプリケーションがあり、アプリケーションの終了時に少し問題があります。イベントハンドラーでTThread.Terminateメソッドを呼び出すことでスレッドを正しく終了できますForm1.OnDestroyが、終了に時間がかかるため、(TThread.Freeメソッドで)メモリを解放できません。残念ながら、他の理由でTThread.FreeOnTerminateプロパティをfalseに設定する必要があるため、スレッドの終了後にスレッドオブジェクトが自動的に破棄されることはありません。

私の質問はおそらく少しばかげているので、ずっと前に知っていたはずですが、これで問題なくスレッドが自動的に破棄されるのでしょうか(アプリケーションが終了したばかりなので)、それとも問題でメモリが「失われる」のでしょうか。 ?説明ありがとうございます。

4

5 に答える 5

7

アプリケーションの残りをシャットダウンするプロセスを開始する前に、スレッドが終了するのを待つ必要があります。そうしないと、共有リソースがスレッド足元で解放され、一連のアクセス違反が発生する可能性があります。スレッドの終了を待った後、スレッドを解放できます。実際、それがTThreadデストラクタが行うことです。

共有リソースがない場合は、もちろん、自然に消滅させてください。スレッドがメイン スレッドの後に終了した場合でも、プログラムを終了するには、すべてのスレッドを終了するだけで済みます。スレッドのオブジェクトに関連付けられたメモリはすべてクリーンアップされ、他のすべてのものとともに OS に返されます。

しかし、注意してください!スレッドが終了するのに時間がかかる場合、そこに座っているゾンビ プロセスが GUI を使わずにかき回される可能性があります。そのため、スレッド ループ内で頻繁にフラグをチェックし、スレッドを終了することが非常に重要です。Terminated

N@

于 2010-07-09T05:47:51.423 に答える
4

あなたの質問は愚かでも単純でもありません。MSDN の記事を読んでください。全体として、安全を確保したい場合は、バックグラウンド スレッドが終了するのを待ってからアプリケーションを終了することをお勧めします。

于 2010-07-09T05:07:04.377 に答える
1

スレッドは最終的に終了し、Windowsは残っているメモリをすべてクリーンアップします。ただし、スレッドが終了するのを待つ方がよいでしょう。これは、Windowsがとにかく行うこととまったく同じだからです。すべてのウィンドウが閉じられている/非表示になっている可能性があるため、アプリケーションがシャットダウンしたように見える場合がありますが、すべてのスレッドが終了するまでアプリケーションプロセスは終了しません...

于 2010-07-09T06:19:11.157 に答える
0

プロセスが終了すると、OSは割り当てられたすべてのメモリを再利用し、開いているすべてのハンドルを閉じます。アプリケーションをシャットダウンするという非常に特別なイベントでリークするMEMORY*)について心配する必要はありません。OSは、少なくとも理論的には、開いているすべてのハンドルを閉じます**)。これらすべてを考慮に入れると、他の共有リソースを強制終了する前に、フォームデストラクタからスレッドを( TerminateThread(MyThread.Handle)を使用して)終了するだけで安全な場合があります。それらの質問を自問してください:

  1. スレッドは何をしていますか?いつでも終了しても安全ですか?例:スレッドがディスクへの書き込みを行っている場合、ディスク上のファイルが不整合な状態で存在する可能性があるため、スレッドを強制終了することは安全ではありません。
  2. Windowsによって自動的に解放されないリソースを使用していますか?ここで良い例を考えることはできません...

両方で安全を確保している場合は、TerminateThreadを使用して、スレッドが自然に終了するのを待つ必要はありません。より安全なアプローチは組み合わせたアプローチかもしれません。スレッドを自然に終了する機会を与え、5秒以内に終了しなかった場合は、強制的に終了する必要があります。

*)メモリについて話しているのは、プロセスの終了時にのみリークを証明できることです。たとえば、スレッドを適切にシャットダウンせずに強制終了したり、解放しないグローバルシングルトンクラスなどです。これはバグであるため、他のすべてのアカウントされていないメモリを追跡して修正する必要があります。

**)残念ながら、WindowsOSにはバグがありません。例:Windowsプラットフォームでシリアルデバイスを操作したことがある人なら誰でも、シリアルデバイスを「ロック」状態にするのがいかに簡単かを知っています。再び動作させるには再起動が必要です。技術的には、これはハンドルでもあり、ロックしたアプリケーションを最終処理すると、ロックが解除されます。

于 2010-07-09T06:01:31.820 に答える
0

スレッドの作成時に変数をインクリメントせず、破棄イベントでスレッドが終了するまで待機し、変数をデクリメントし、アプリケーション終了時に Application.processmessages を実行するのはなぜですか?

あなたのスレッドが freeonterminate=true ではないのはなぜですか? すべての共有リソースをクリティカル セクションで処理できます。

よろしくお願いします、

于 2010-07-09T07:43:12.103 に答える