2

これは、システムプロセスを終了することではなく、「自分自身」を殺すことです。私はいくつかの並列のtheadを持っていますが、さまざまな理由でハングする可能性があります。

スレッドに時間がかかりすぎる場合は、すでにウォッチドッグを作成しました。

TimerCallback timerDelegate = new TimerCallback(CheckProcessStatus);
System.Threading.Timer watchDogTimer = new Timer(timerDelegate, new ProcessHealth(plog), 1000 * 60, 1000 * 60);
try
   {
   // lots of code here
   } finally
   {
      watchDogTimer.Dispose();
   }

ウォッチドッグ:

public void CheckProcessStatus(Object timerState) {
    ProcessHealth ph = (ProcessHealth)timerState;
    System.writeLine(string.Format("process runs for {0} minutes!", ph.WaitingTime);
    if (ph.WaitingTime>60) {
      // KILL THE PROCESS
    }
}

「ここにたくさんのコード」が長すぎる場合は、スレッドがどのような状態であっても、スレッドを終了したいと思います(「プロセスの強制終了」で)。

最善のアプローチは何でしょうか?

Thread.CurrentThread.Interrupt()

また

Thread.CurrentThread.Abort()?

それとももっと良いアプローチがありますか?(ブール値の「stop」変数のような「単純な」メカニズムは使用できません。「ここにたくさんのコード」があるため、リフレクションなどを介して他のクラスを非常に動的に呼び出します。

それも機能しますか?または、監視対象のスレッドではなく、ウォッチドッグスレッドを強制終了しますか?

4

2 に答える 2

3

スレッドが不明な状態にあるときにスレッドを中止することはお勧めできません。たとえば、スレッドは現在静的コンストラクターを実行しています。静的ctorは中止され、二度と実行されません(障害のある静的ctorは二度と実行されないため)。AppDomainのグローバル状態を、回復する方法なしに効果的に破棄しました。

他にもたくさんの危険があります。それは飛ばないだけです。

スレッドを中止する2つの本番環境対応の選択肢があります。

  1. 協調的に(Thread.MemoryBarrierと組み合わせてイベントまたはブールフラグを設定します)
  2. スレッドを中止しないでください。AppDomain全体またはプロセスを中止してください。スレッドレベルの粒度が小さすぎます。そのスレッドに関連するすべての状態を削除する必要があります、doo。

これを他の方法で機能させることはできないことを強調したいと思います。非協力的にスレッドを中止することを主張すると、本番環境で最も奇妙な障害が発生します。

于 2012-06-01T13:08:04.183 に答える
3

Thread.Abort帯域外(非同期)例外を挿入することにより、ターゲットスレッドを終了しようとします。実行シーケンスの予測できないポイントに例外が挿入されるため、安全ではありません。これにより、データ構造への書き込みが中断されるため、アプリケーションドメインで何らかの種類の破損が発生する可能性があります(多くの場合、発生します)。

Thread.InterruptBCL内のほとんどのブロッキング呼び出し(Thread.SleepWaitHandle.WaitOneなど)がすぐにベイルアウトします。スレッドの中止とは異なり、実行シーケンスの予測可能なポイントに例外挿入されるため、スレッドの中断は完全に安全になります。巧妙なプログラマーは、これらのポイントが「安全なポイント」と見なされることを確認できます。

したがって、「ここにたくさんのコード」が応答するThread.Interrupt場合は、それを使用するのが許容できるアプローチである可能性があります。しかし、私はあなたを協力的なキャンセルパターンに向けてもっと導きたいと思います。基本的に、これは、コードがキャンセル要求を定期的にポーリングする必要があることを意味します。TPLには、を介してこれを行うためのフレームワークがすでに用意されていCancellationTokenます。ManualResetEventただし、または単純な揮発性ブール変数を使用して、同じことを簡単に実行できます。

さて、「ここにたくさんのコード」があなたの管理下にない場合、または協調キャンセルパターンが機能しない場合(おそらく欠陥のあるサードパーティライブラリを使用しているため)、完全に分離してスピンアップする以外に選択肢はほとんどありません危険なコードを実行するプロセス。WCFを使用してプロセスと通信し、WCFが応答しない場合は、メインプロセスを破損することなくWCFを強制終了できます。大変な作業ですが、それが唯一の選択肢かもしれません。

于 2012-06-01T14:28:55.597 に答える