2017-11-14 14 views
4

スレッドバージョンでは処理されない例外が発生し、アプリケーションはクラッシュしますが、タスクバージョンでは発生しません。両方ともまったく同じメソッドを実行しています誰かがこの例外の動作の違いの理由を説明することはできますか?例外処理:スレッドv/sタスク

スレッドバージョン:

  try 
      { 
       new Thread(new ThreadStart(DoWork)).Start(); // do work throws exception 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
      } 

     static void DoWork() 
     { 
      Console.WriteLine("in thread"); 
      throw new Exception(); 
     } 

タスクのバージョン:

 var errorTask = Task.Factory.StartNew<Func<string>>(() => 
       { 
        Console.WriteLine("in task"); 
        throw new Exception(); 
       }); 

      try 
      { 
       string result = errorTask.Result(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
      } 
+0

タスク!=スレッドです。 – john

+0

@johnええ、初心者にとっては動作がかなり似ていますので、xeは例外の処理方法が邪魔になることが考えられます。 –

答えて

3

Thread.Start開始新しいスレッド、あなたが別のスレッドで例外を処理していますが:新しい

try 
{ 
    // DoWork throws exception in new thread; 
    // threads don't catch exceptions out-of-the-box 
    new Thread(new ThreadStart(DoWork)).Start(); 
} 
catch (Exception e) 
{ 
    // you're handling exception in "old" thread 
    Console.WriteLine(e); 
} 

Task.Factory.StartNew開始タスク。タスクは、そのStatusプロパティを設定し、その中に例外をキャッチ:あなたはTask.Resultを取得しようとしている、とタスクがフォルト状態にあるとき

var errorTask = Task.Factory.StartNew<Func<string>>(() => 
{ 
    Console.WriteLine("in task"); 

    // this exception will be caught in Task's base code, 
    // since tasks catch exceptions thrown by task methods; 
    // note, that this will be wrapped into AggregateException 
    throw new Exception(); 
}); 

、それだけで再スロー例外:

// this will re-throw exception in calling thread 
string result = errorTask.Result; 

理由ですことあなたの2番目のcatchがそれをキャッチします。

1

documentationTask.Result<TResult>()(またはTask.Wait()はそれが価値があるもの)と尋ねることができます。

スローされた例外の下で

(特にAggregateException)であるが、例外は、タスクの実行中にスローされた

言います。 AggregateException.InnerExceptionsコレクションには、例外または例外に関する情報が含まれています。

Taskは管理スレッドの一種です(非常に簡単に言えば)、いくつかのメリットがあります。 ResultまたはWaitにアクセスする場合(またはawaitを使用して)、この例外処理が行われます。一方、Threadは、呼び出し元のメソッドとは別に実行されます。あなたはすぐにtry/catchブロックを離れてスレッドを開始します(事実上)。 にはtry/catchというスレッドがあるので、を知る方法はありません。基本的に、スレッドは呼び出し関数について何も知らない。呼び出し元の関数が自身が作成したスレッドを待つために独自のスレッドをブロックした場合は、try/catchを使用するだけで、基本的には新しいスレッドを作成することができなくなります。