プログラミングBlog

C# Threadの例外をCatchする。

Threadを使った非同期処理時に例外が発生した場合の動作について。

Excute()

Threadの実行クラス。ここでGreet()メソッドを呼び出します。

public static void Excute() {
          try
          {
              Thread thread = new Thread(new ThreadStart(Greet));
              thread.Start();
          }
          catch (Exception ex)
          {
              Console.WriteLine(ex.Message);
          }
          finally
          {
              Console.WriteLine("終了");
          }
}

Greet()

挨拶するクラス。 挨拶失敗して例外発生します。

public static void Greet(){
          try
          {
              // ここで例外発生!
              Console.WriteLine("Hello");
          }
          catch (Exception ex)
          {
              Console.WriteLine(ex.Message);
              throw ex;
          }
}

期待している動作としては Greetメソッドにて例外発生した後、throw exでExcuteメソッドに投げた例外をcatchしてほしい。 その後のfinallyにて終了を表示してほしい。
なんかエラーが出ました。。
f:id:Tokuty:20210106204054p:plain
Greetメソッドの例外でエラーが出てしまい、動作が終了しました。
ハンドルされていない例外、例外がCatchされなかったようです。
今の状態だと例外が発生した時点で処理が終了してしまうので期待している動作ではありません。

Excute() 修正版

Excuteメソッドを修正しました。

public static void Excute() 
      {
          Thread thread = new Thread(() =>
          {
              try
              {
                  Greet();
              }
              catch (Exception ex)
              {
                  Console.WriteLine(ex.Message);
              }
          });
          thread.Start();
}

無事動きました!デバッグで確認しましたが、Greet()が先に呼ばれそうでしたが、
thread.Start()が呼ばれてからGreet()が呼ばれていたのでこの書き方でもいけるようです。

感想

Threadが古い書き方で今はTaskを使うのが主流みたいですが、Replace案件が最近増えている(COBOLC#,VB6→C#などなど)ので、 Threadも扱えた方が良い。
非同期、同期の考え方自体が難しいので簡単なアプリを作って動作確認しながらやるのが一番わかりやすそう。
動くけど、今回のように不具合が発生する場合もあるのでいろいろ試した方が良さそう。