「C Sharpの基礎 - 例外処理」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(Wiki がページ「適切に処理されなかった例外をキャッチする(C Sharp)」を「C Sharpの基礎 - 例外処理」に、リダイレクトを残さずに移動しました)
編集の要約なし
1行目: 1行目:
== 概要 ==
== 概要 ==
Windowsフォームやコンソールを実装する際、例外が発生する可能性がある個所では、<br>
Windowsフォームやコンソールを実装する際、例外が発生する可能性がある個所では、<br>
Try-Catch構文によりその例外をキャッチして適切な処置を施す必要がある。<br><br>
Try-Catch構文によりその例外をキャッチして適切な処置を施す必要がある。<br>
しかし、現実には例外が正しくキャッチ(トラップ)されていないというケースは多々あり、<br>
<br><br>
その場合にはアプリケーションの実行中に次のような.NET Framework標準のエラーダイアログが表示されてしまうことになる。<br>
 
== 処理されていない例外をハンドルする ==
一般的に、例外が正しくキャッチ(トラップ)されていないというケースは多々ある。<br>
<br>
その場合、ソフトウェアの実行中において、以下のような.NET Framework標準のエラーダイアログが表示されてしまう。<br>
このエラーダイアログは、ユーザにとって理解しにくい。<br>
[[ファイル:Catch exception 01.gif|フレームなし|中央]]
[[ファイル:Catch exception 01.gif|フレームなし|中央]]
<br>
<br>
このエラーダイアログは、一般ユーザにとって理解しにくい。PCの操作に自信のない人であれば、これを見た途端に困惑してしまう。<br>
これを避けるために、.NET Framework標準のエラーダイアログを、自作のエラーダイアログに切り替えたいという要望も多い。<br>
この事態を避けるために、.NET Framework標準のエラーダイアログを、ユーザライクな自作のエラーダイアログに切り替えたいという要望も多い。<br><br>
<br>
ここでは、Windowsフォームやコンソールで処理されていない例外を1カ所でまとめてハンドルする方法を記載する。<br>
ここでは、処理されていない例外を1ヶ所に纏めてハンドルする方法を記載する。<br>
この方法により、ハンドルしたメソッド内で独自に作成したエラーダイアログを表示すれば、前述の要望も実現可能である。<br><br>
この方法により、ハンドルしたメソッド内で独自に作成したエラーダイアログを表示すれば、前述の要望も実現可能である。<br>
 
<br>
== 処理されていない例外をハンドルするには ==
* Application.ThreadExceptionイベントの活用
* '''Application.ThreadExceptionイベントの活用'''
*: 処理されなかった例外をハンドルするには、WindowsフォームならApplicationクラス(System.Windows.Forms名前空間)の
:処理されなかった例外をハンドルするには、WindowsフォームならApplicationクラス(System.Windows.Forms名前空間)の
*: ThreadExceptionイベントをハンドルして処理する。
:ThreadExceptionイベントをハンドルして処理する。
*: このイベントは、Windowsフォームのメインスレッド(ApplicationクラスのRunメソッドにより実行されるアプリケーションのコンテキスト)内で
:このイベントは、Windowsフォームのメインスレッド(ApplicationクラスのRunメソッドにより実行されるアプリケーションのコンテキスト)内で
*: 発生した未処理の例外をハンドルするためのものである。
:発生した未処理の例外をハンドルするためのものである。
*: <br>
 
* Thread.GetDomain().UnhandledExceptionイベントの活用
* '''Thread.GetDomain().UnhandledExceptionイベントの活用'''
*: では、上記のメイン・スレッド以外のコンテキスト上で発生した例外は、
:では、上記のメイン・スレッド以外のコンテキスト上で発生した例外は、
*: 現在のアプリケーションドメイン(AppDomainクラス(System名前空間)のThread.GetDomainメソッドにより取得できる)の
:現在のアプリケーションドメイン(AppDomainクラス(System名前空間)のThread.GetDomainメソッドにより取得できる)の
*: UnhandledExceptionイベントで出来る。
:UnhandledExceptionイベントで出来る。
*: 例えば、マルチスレッド処理において、メインスレッド以外のスレッドで発生した例外やコンソールで発生した例外等は、
:例えば、マルチスレッド処理において、メインスレッド以外のスレッドで発生した例外やコンソールで発生した例外等は、
*: 全てこのUnhandledExceptionイベントをハンドルして処理すればよい。
:全てこのUnhandledExceptionイベントをハンドルして処理すればよい。
<br>
 
以下の例では、上記2つのイベントを活用して、未処理の例外を実際に処理している。<br>
上記2つのイベントを活用して未処理の例外を実際に処理しているのが、次のサンプルコードである。<br><br>
  <syntaxhighlight lang="c#">
 
== サンプルコード ==
  <source lang="cpp">
  using System;
  using System;
  using System.Windows.Forms;
  using System.Windows.Forms;
79行目: 81行目:
     }
     }
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:C_Sharp]]
[[カテゴリ:C_Sharp]]

2021年3月26日 (金) 22:15時点における版

概要

Windowsフォームやコンソールを実装する際、例外が発生する可能性がある個所では、
Try-Catch構文によりその例外をキャッチして適切な処置を施す必要がある。


処理されていない例外をハンドルする

一般的に、例外が正しくキャッチ(トラップ)されていないというケースは多々ある。

その場合、ソフトウェアの実行中において、以下のような.NET Framework標準のエラーダイアログが表示されてしまう。
このエラーダイアログは、ユーザにとって理解しにくい。

Catch exception 01.gif


これを避けるために、.NET Framework標準のエラーダイアログを、自作のエラーダイアログに切り替えたいという要望も多い。

ここでは、処理されていない例外を1ヶ所に纏めてハンドルする方法を記載する。
この方法により、ハンドルしたメソッド内で独自に作成したエラーダイアログを表示すれば、前述の要望も実現可能である。

  • Application.ThreadExceptionイベントの活用
    処理されなかった例外をハンドルするには、WindowsフォームならApplicationクラス(System.Windows.Forms名前空間)の
    ThreadExceptionイベントをハンドルして処理する。
    このイベントは、Windowsフォームのメインスレッド(ApplicationクラスのRunメソッドにより実行されるアプリケーションのコンテキスト)内で
    発生した未処理の例外をハンドルするためのものである。

  • Thread.GetDomain().UnhandledExceptionイベントの活用
    では、上記のメイン・スレッド以外のコンテキスト上で発生した例外は、
    現在のアプリケーションドメイン(AppDomainクラス(System名前空間)のThread.GetDomainメソッドにより取得できる)の
    UnhandledExceptionイベントで出来る。
    例えば、マルチスレッド処理において、メインスレッド以外のスレッドで発生した例外やコンソールで発生した例外等は、
    全てこのUnhandledExceptionイベントをハンドルして処理すればよい。


以下の例では、上記2つのイベントを活用して、未処理の例外を実際に処理している。

 using System;
 using System.Windows.Forms;
 using System.Threading;
 
 namespace WindowsApplication1
 {
    public class Program
    {
       [STAThread]
       static void Main()
       {
          // ThreadExceptionイベント・ハンドラを登録する
          Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
 
          // UnhandledExceptionイベント・ハンドラを登録する
          Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(Application_UnhandledException);
 
          // メイン・スレッド以外の例外はUnhandledExceptionでハンドル
          //string buffer = "1"; char error = buffer[2];
 
          // ここで実行されるメインスレッドの例外はApplication_ThreadExceptionでハンドルできる
          Application.Run(new Form1());
       }
 
       // 未処理例外をキャッチするイベントハンドラ
       // (Windowsアプリケーション用)
       public static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
       {
          ShowErrorMessage(e.Exception, "Application_ThreadExceptionによる例外通知です。");
       }

       // 未処理例外をキャッチするイベントハンドラ
       // (主にコンソール用)
       public static void Application_UnhandledException(object sender, UnhandledExceptionEventArgs e)
       {
          Exception ex = e.ExceptionObject as Exception;
          if (ex != null)
          {
             ShowErrorMessage(ex, "Application_UnhandledExceptionによる例外通知です。");
          }
       }

       // ユーザー・フレンドリなダイアログを表示するメソッド
       public static void ShowErrorMessage(Exception ex, string extraMessage)
       {
          MessageBox.Show(extraMessage + @" \n――――――――\n\n" + @"エラーが発生しました。開発元にお知らせください\n\n" +
                          @"【エラー内容】\n" + ex.Message + "\n\n" + @"【スタックトレース】\n" + ex.StackTrace);
       }
    }
 }