7

ユーザーがアプリケーションをシャットダウンしたいときに、IO (HTTP 呼び出しなど) を実行するのにビジーである可能性がある多数のスレッドを持つ C++ Win32 アプリケーションがあります。現在、私はうまくプレイし、すべてのスレッドが終了するのを待ってから に戻りmainます。時々、これには私が望むよりも時間がかかります。実際、終了できるときにユーザーを待たせるのは無意味に思えます。ただし、先に進んでから戻るとmain、オブジェクトを使用しているスレッドがまだある間にデストラクタが呼び出され始めるため、クラッシュする可能性があります。

では、理想的でプラトニックな美徳の世界では、すべてのスレッドが終了するのを待ってから正常にシャットダウンするのが最善であることを認識すると、次善の現実世界のソリューションは何でしょうか? 単純にスレッドの終了を高速化することは、オプションではない場合があります。目標は、たとえば、新しいバージョンをその上にインストールできるように、プロセスをできるだけ早く停止することです。私が行っている唯一のディスク IO はトランザクション データベース内にあるため、プラグを抜くことについてはそれほど心配していません。

4

11 に答える 11

7

オーバーラップ IO を使用して、I/O を処理しているスレッドを常に制御し、いつでも停止できるようにします。それらをIOCPで待機させて、アプリケーションレベルのシャットダウンコードをポストするか、またはOVERLAPPED構造のイベントを待機し、「すべてのスレッドを今すぐシャットダウンしてください」イベントも待機できます。

要約すると、キャンセルできない通話をブロックすることは避けてください。

それができず、IO を実行しているブロッキング ソケット呼び出しでスタックしている場合は、いつでも、シャットダウンする時が来たと判断したスレッドからソケットを閉じて、IO を実行しているスレッドに常に「今すぐシャットダウン」をチェックさせることができます。 ' 再試行前のイベント...

于 2008-10-16T19:42:26.753 に答える
5

私は、多くの Win32 アプリケーションで非常にうまく機能している例外ベースの手法を使用しています。

スレッドを終了するQueueUserAPC()には、例外をスローする関数の呼び出しをキューに入れます。ただし、スローされる例外は「Exception」型から派生したものではないため、スレッドのラッパー プロシージャによってのみキャッチされます。

これの利点は次のとおりです。

  • スレッドを「停止可能」にするためにスレッドに特別なコードは必要ありません。スレッドがアラート可能な待機状態になるとすぐに、APC 関数が実行されます。
  • 例外がスタックを駆け上がると、すべてのデストラクタが呼び出されるため、スレッドは正常に終了します。

あなたが注意する必要があること:

  • 何かをcatch (...)すると、例外が食べられます。ユーザーコードは常にcatch(const Exception &e)または同様のものを使用する必要があります!
  • I/O と遅延が「アラート可能な」方法で行われていることを確認してください。たとえば、これはsleepex(N, true)の代わりに呼び出すことを意味しsleep(N)ます。
  • CPU バインド スレッドはsleepex(0,true)、終了を確認するために時々呼び出す必要があります。

コードの領域を「保護」して、重要なセクションでのタスクの終了を防ぐこともできます。

于 2008-10-16T21:30:52.633 に答える
2

GUI と作業を別のスレッドで行うことをお勧めします。ユーザーがシャットダウンを要求すると、すぐに GUI を閉じて、アプリケーションが閉じたように見えます。ワーカー スレッドがバックグラウンドで正常に終了できるようにします。

于 2008-10-16T15:56:35.803 に答える
2

最善の方法: アプリの実行中に作業を行い、シャットダウン時には何も (またはほぼ) 何もしません (起動時にも機能します)。そのパターンに固執すると、シャットダウン要求が来たときに、まだ実行する必要がある作業について心配することなく、スレッドをすぐに破棄できます (それについて「親切にする」のではなく)。

あなたの特定の状況では、そこでローカル作業を行っている場合、おそらく IO が終了する (少なくとも書き込み) まで待つ必要があります。HTTPリクエストなどは、おそらく完全に放棄/クローズできます(これも、何かを書いている場合を除きます)。ただし、このシャットダウン中に書き込みを行って待機している場合は、処理中にプロセスがハングしたように見せるのではなく、ユーザーにそのことを通知することをお勧めします。

于 2008-10-16T15:42:42.697 に答える
0

突然シャットダウンする必要がある場合:ExitProcessを呼び出すだけです。これは、とにかくWinMainから戻った直後に呼び出されるものです。Windows自体は、クリーンアップする方法がない多くのワーカースレッドを作成します。これらは、プロセスのシャットダウンによって終了します。

ある種の書き込みを実行しているスレッドがある場合、明らかにそれらはリソースを閉じる機会が必要です。しかし、それ以外の場合は、境界チェッカーの警告を無視して、足元からラグを引っ張ってください。

于 2008-10-17T11:35:55.173 に答える
0

TerminateProcess を呼び出すことができます。これにより、誰にも通知せず、何も待たずに、プロセスがすぐに停止します。

于 2008-10-17T12:03:01.033 に答える
0

プラグを乱雑に引き抜きたい場合は、 exit(0) がそのトリックを行います。

于 2008-10-16T15:51:39.840 に答える
0

*NULL = 0が最速の方法です。クラッシュしたくない場合は、exit()またはそれに相当する win32 を呼び出してください。

于 2011-12-09T02:32:29.687 に答える
0

何をするにしても、TerminateThread を使用しないでください特に、OS の HTTP 呼び出しに含まれる可能性があるものには使用しないでください。再起動するまで IE が壊れる可能性があります。

すべての IO を非同期または非ブロッキング モデルに変更して、終了イベントを監視できるようにします。

于 2008-10-16T21:09:48.917 に答える
0

Visual Basic 6 でも同様の問題がありました。アプリからのスレッドが別のサーバーに接続し、データをダウンロードし、そのデータをループする操作を実行し、結果を中央サーバーに保存します。

次に、スレッドはメイン フォームから停止可能にする必要があるという新しい要件がありました。特定の名前でミューテックスを開こうとする N ループ (およそ 0.5 秒に相当) の後にスレッドを停止させることで、簡単ではあるが汚れた方法でこれを実現しました。成功すると、彼らはすぐに何をしていたとしてもやめ、それ以外は続けました。

このミューテックスはメイン フォームによってのみ作成され、作成されるとすぐにすべてのスレッドが閉じられます。欠点は、ユーザーがスレッドを再度実行したいことを手動で指定する必要があることでした-「スレッドの実行を有効にする」ための別のボタンは、ミューテックスを解放することでこれを実現しました:D

このトリックは、ミューテックス操作がアトミックである場合に機能することが保証されています。問題は、スレッドが実際に閉じられていることを確認できないことです。「openMutex が成功した」ケースを処理するロジックの失敗は、スレッドが終了しないことを意味する可能性があります。また、すべてのスレッドがいつ/閉じたかどうかもわかりません (コードが正しいと仮定すると、ループが停止して「リッスン」するのにかかる時間とほぼ同じ時間がかかります)。

VB のマルチスレッドの「アパートメント」モデルでは、スレッドからメイン アプリに情報をやり取りするのはやや難しく、「ファイア アンド フォーゲット」またはメイン アプリからスレッドのみに情報を送信する方がはるかに簡単です。したがって、この種のロングカットが必要です。C++ を使用すると、マルチスレッド モデルを自由に使用できるため、これらの制約が適用されない場合があります。

于 2008-10-16T20:27:40.983 に答える
-5

ユーザーにコンピュータのプラグを抜くように指示します。それ以外では、非同期アクティビティを風に任せる必要があります。それともHWINDですか?C ++では覚えられません。もちろん、途中でテキスト ファイルまたはレジストリ キーにどのアクションが破棄されたかをすばやく書き留めて、次にプログラムを実行するときにそのアクションを自動的に再度実行するか、ユーザーに実行するかどうかを尋ねることもできます。非同期アクションを放棄したときに失うデータによっては、それができない場合があります。ユーザーと対話している場合は、対話に時間がかかる理由を説明するダイアログまたは何らかの UI 対話を検討することをお勧めします。

個人的には、コンピューターのプラグを抜くようにユーザーに指示することを好みます。:)

于 2008-10-16T15:50:09.093 に答える