4

プログラムで処理されていない例外をキャッチしようとしています。このコードをプログラムのメインクラスで使用しています。

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

AppDomain.CurrentDomain.UnhandledException += new    UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

Application.Run(new Form1());
}


public static void CurrentDomain_UnhandledException(Object sender,  UnhandledExceptionEventArgs e)
{

MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled domain Exception");
Application.Exit();
}

今度はフォームform1で、単純な例外を作成しようとします。trycatchブロックなしでゼロ除算を行うと、メインモジュールのコードが実際に例外をインターセプトしますが、MSVisualStudioダイアログが表示されます。アプリケーションは終了しません。もちろん、実際の状況では、エラーをログに記録/メールで送信します。しかし、例外をインターセプトした後も実行が継続する理由を理解したいのですが?ありがとう

4

3 に答える 3

9

メイン UI スレッドからすべての例外をキャッチすると、うまくいきました。

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Add handler for UI thread exceptions
            Application.ThreadException += new ThreadExceptionEventHandler(UIThreadException);

            // Force all WinForms errors to go through handler
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

            // This handler is for catching non-UI thread exceptions
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            Application.Run(new Form1());
        }

        private static void CurrentDomain_UnhandledException(Object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                Exception ex = (Exception)e.ExceptionObject;
                MessageBox.Show("Unhadled domain exception:\n\n" + ex.Message);
            }
            catch (Exception exc)
            {
                try
                {
                    MessageBox.Show("Fatal exception happend inside UnhadledExceptionHandler: \n\n"
                        + exc.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
                finally
                {
                    Application.Exit();
                }
            }

            // It should terminate our main thread so Application.Exit() is unnecessary here
        }

        private static void UIThreadException(object sender, ThreadExceptionEventArgs t)
        {
            try
            {
                MessageBox.Show("Unhandled exception catched.\n Application is going to close now.");
            }
            catch
            {
                try
                {
                    MessageBox.Show("Fatal exception happend inside UIThreadException handler",
                        "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
                }
                finally
                {
                    Application.Exit();
                }
            }

            // Here we can decide if we want to end our application or do something else
            Application.Exit();
        }
    }
于 2012-05-14T10:34:52.473 に答える
1

Application.ExitまたはEnvironment.Exitを使用する必要はありません。これは、インターセプトし続けるビジュアルスタジオの動作であり、処理されない例外の行を引き起こしますが、実際には、isTerminatingフラグが設定されている場合、アプリケーションはクラッシュ(終了)します、これは正しい使い方です。これにはユーザーインターフェイスを使用しないことをお勧めします。また、このイベントでは、サイレントログだけでリソースを大量に消費するプロセスを使用しないことをお勧めします。

このイベントの目的は、それが正確に発生した理由のログを取得することです。これは、アプリケーションがクラッシュしている間、またはこれについてユーザーに謝罪している間、アプリケーションの見栄えを良くするためのポイントではありません。ただし、ユーザーが次回ログインするときに上記を実行する機会があります。

したがって、例外ログを電子メールで送信することを計画している場合でも、ファイルを書き込んで、アプリケーションの次回の起動時にそのファイルを電子メールで送信するのが最善の方法です。

私は通常 log4net を使用し、これらのイベントを次のように使用します。

[STAThread]
static void Main()
{
    log.Info("Starting deployer application");

    Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
    Application.ApplicationExit += new EventHandler(Application_ApplicationExit);

    Application.Run(ConnectionForm.GetInstance);
}

static void Application_ApplicationExit(object sender, EventArgs e)
{
    log.Info("Application Closed");
}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    log.Error(string.Format("*** UNHANDLED APPDOMAIN EXCEPTION ({0}) *****", e.IsTerminating ? "Terminating" : "Non-Terminating"), e.ExceptionObject as Exception);
}

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
    log.Error("*** UNHANDLED THREAD EXCEPTION *****", e.Exception);
}

以前に log4net を使用したことがない場合は、これが役立ちます

于 2013-11-28T01:10:43.683 に答える
0
Use Environment.Exit() 

それ以外の

Application.Exit()
于 2013-10-08T10:42:06.947 に答える