다른 스레드에서 예외 발생시 프로그램 종료되는 이유가 궁금합니다.


위 예제를 참고해서

Program.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            Application.Run(new ErrorHandlerForm());
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            string now = DateTime.Now.ToString("yyyyMMdd_HHmmss");
            string exceptionLog = e.Exception.Message;
            string msg = "Unhandled Thread Exception";
            string log = msg + " : " + exceptionLog;
            System.IO.File.WriteAllText(System.Windows.Forms.Application.StartupPath + @"/exception_log/" + now + @".txt", log);
            MessageBox.Show(exceptionLog, msg);
            // here you can log the exception ...
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            string now = DateTime.Now.ToString("yyyyMMdd_HHmmss");
            string exceptionLog = (e.ExceptionObject as Exception).Message;
            string msg = "Unhandled UI Exception";
            string log = msg + " : " + exceptionLog;
            System.IO.File.WriteAllText(System.Windows.Forms.Application.StartupPath + @"/exception_log/" + now + @".txt", log);
            MessageBox.Show(exceptionLog, msg);
            // here you can log the exception ...
        }

    }
}

ErrorHandlerForm.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class ErrorHandlerForm : Form
    {
        Thread newThread = null;
        public ErrorHandlerForm()
        {
            InitializeComponent();
        }

        // Programs the button to throw an exception when clicked.
        private void button1_Click(object sender, System.EventArgs e)
        {
            throw new ArgumentException("The parameter was invalid");
        }

        // Start a new thread, separate from Windows Forms, that will throw an exception.
        private void button2_Click(object sender, System.EventArgs e)
        {
            ThreadStart newThreadStart = new ThreadStart(newThread_Execute);
            newThread = new Thread(newThreadStart);
            newThread.Start();
        }
        // The thread we start up to demonstrate non-UI exception handling. 
        void newThread_Execute()
        {
            throw new Exception("The method or operation is not implemented.");
        }

    }
}

button1, button2 만들어서 이벤트 핸들러 추가해줬고요.
이런 윈폼을 빌드한 다음에 exe를 따로 실행시켜보면
button1, button2를 각각 눌렀을 때 예외로그 txt파일은 정상적으로 저장되는데
button1을 눌렀을 때는 프로그램이 종료되지 않고 button2를 눌렀을 때는 프로그램이 종료됩니다.
아마 다른 스레드에서 예외를 발생시켰기 때문에 그런 걸 거라고는 추측해볼 수 있는데.
정확히 왜 그런 건지, 어떻게 하면 button2를 눌러도 프로그램이 종료되지 않을지 궁금합니다.

유저모드의 프로세스안 스레드에서 예외가 발생하고 이를 처리할 주체가 아무도 없다면,
시스템은 프로세스를 종료시켜버립니다.

이런 디자인은 매우 직관적이며, 당연하다고 볼 수 있죠.

자 그럼 문제를 살펴봅시다.
예외를 처리할 수 있게 핸들러를 등록을 해놓으셨네요.

그런데 새로이 스레드를 만드시면 자동으로 만든 스레드에서 메인 스레드로 예외를 던져주지 않습니다.
즉, 두개의 스레드의 예외처리과정은 별개죠.

그래서 이런 현상이 발생하는 겁니다.

비슷한 기능을 .NET환경에서 구현하고 싶으시다면.
Task 를 검색해보세요.

3 Likes

이름 붙이는 법이 심각하다고 봅니다