2017-12-13 14 views
0

私はスレッドとParallel.Foreachで特別な設定を持っています:別スレッドでParallel.Foreachループが実行されます。関数Abort()を呼び出すことによってThreadが中止されることがあります。私は奇妙な行動を得る:複数回ThreadAbortExceptionがスローされます。誰かがここで何が起きているのか、何が良い解決策になるのか説明できますか?スレッドを中止する際の別のスレッドの動作

システム:以下

  • のVisual Studio 2017
  • C#7.0
  • の.Net 4.6.1

コード。

static void Main(string[] args) 
    { 
     //Start the new Thread 
     Thread workerThread = new Thread(Program.TestVoid); 
     workerThread.Name = "My WorkerThread"; 
     workerThread.Start(); 

     //wait 
     Thread.Sleep(1000); 

     //abort thread 
     workerThread.Abort(); 
    } 

    public static void TestVoid() 
    { 
     bool[] liBools = new bool[10000]; 

     Parallel.For(0, liBools.Length, idx => 
     { 
      liBools[idx] = idx == 9998; 
     }); 

     try 
     { 
      Parallel.ForEach(liBools, myBool => 
      { 
       try 
       { 
        //do something 
        Thread.Sleep(1000); 
       } 
       catch (Exception ex) //Thread Abort Exception get caught 
       { 

       } 
      }); 
     } 
     catch (OperationCanceledException ex) 
     { 

     } 
     catch (ThreadAbortException ex) //Thread Abort Exception get caught 
     { 

     } //here arises another ThreadAbortException 
     finally 
     { 
      source.Dispose(); 
     } 
     string s = "ready"; 
    } 

答えて

2

私は奇妙な動作を得ます:複数回ThreadAbortExceptionがスローされます。

これは、その例外の正常な動作です:呼び出しがスレッドを破壊するためにAbortメソッドに行われた場合

、共通言語ランタイムは、ThreadAbortExceptionのをスローします。 ThreadAbortExceptionは捕捉可能な特別な例外ですが、catchブロックの最後で自動的に再度発生します。この例外が発生すると、ランタイムはスレッドを終了する前にすべてのfinallyブロックを実行します。スレッドはfinallyブロックで無制限の計算を実行できるため、または中断を取り消すためにThread.ResetAbortを呼び出すことができるため、スレッドが終了する保証はありません。中止されたスレッドが終了するまで待つ場合は、Thread.Joinメソッドを呼び出すことができます。結合はスレッドが実際に実行を停止するまで戻ることのないブロッキング呼び出しです。あなたはその時点で中絶をキャンセルするThread.ResetAbort()を使用することができますが、そうでない場合は、それはほとんど常に良いでしょう(Source

 

良い解決策がどうなるか

Thread.Abort()に電話してください。 Cancellable Taskと揮発性の "今停止してください"ブール値のチェックは2つの選択肢です。あなたのユースケースには他のものが当てはまるかもしれません。 Thread.Abort()は、大きな赤い警告ボタンのシナリオがある場合にのみ予約する必要があります。

0

あなたはdocumentation for Thread.Abortを見ればあなたは、その機能がThreadAbortExceptionをスローすることであることがわかります。それがあなたが望むものでないなら、Thread.Abortを使わないでください。一般的には、Thread.Abortを呼び出すのではなく、呼び出しスタック全体を正常に完了/戻してスレッドを終了する必要があります。 Thread.Abortに電話する必要がある場合は、それに伴う例外を処理する準備ができている必要があります。

関連する問題