Preventing Exception Dialog Unhandled

Let me first say that I read this useful article and I am using the SafeThread class from CodeProject. I get the same result, whether Thread or SafeThread.

I reduced my problem to an application consisting of two forms, each with one button. The main program displays the form. When you click this button, a new stream begins, which displays the second form. When you click a button in the second form, internally it simply "throws a new exception ()"

When I run this under VS2008, I see "Exception in DoRun ()".

When I run outside of VS2008, I get a dialog box "An unhandled exception occurred in your application. If you click continue, the application ..."

I tried to set legacyUnhandledExceptionPolicy in app.config to both 1 and 0.

What do I need to do to catch the exception that was selected in my second form, if it does not work under VS2008?

Here is my program.cs

    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.ThreadException += new ThreadExceptionEventHandler    (Application_ThreadException);
            Application.SetUnhandledExceptionMode    (UnhandledExceptionMode.CatchException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            try
            {
               Application.Run(new Form1());
            }
            catch(Exception ex)
            {
                MessageBox.Show("Main exception");
            }                
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            MessageBox.Show("CurrentDomain_UnhandledException");
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            MessageBox.Show("Application_ThreadException");
        }
    }

Here is Form1:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        SafeThread t = new SafeThread(new SimpleDelegate(ThreadMain));
        try
        {
            t.ShouldReportThreadAbort = true;
            t.ThreadException += new ThreadThrewExceptionHandler(t_ThreadException);
            t.ThreadCompleted += new ThreadCompletedHandler(t_ThreadCompleted);
            t.Start();
        }
        catch(Exception ex)
        {
            MessageBox.Show(string.Format("Caught externally! {0}", ex.Message));

        }
    }

    void t_ThreadCompleted(SafeThread thrd, bool hadException, Exception ex)
    {
        MessageBox.Show("t_ThreadCompleted");
    }

    void t_ThreadException(SafeThread thrd, Exception ex)
    {
        MessageBox.Show(string.Format("Caught in safe thread! {0}", ex.Message));
    }

    void ThreadMain()
    {
        try
        {
            DoRun();
        }
        catch (Exception ex)
        {
            MessageBox.Show(string.Format("Caught! {0}", ex.Message));
        }
    }

    private void DoRun()
    {
        try
        {
            Form2 f = new Form2();
            f.Show();
            while (!f.IsClosed)
            {
                Thread.Sleep(1);
                Application.DoEvents();
            }
        }
        catch(Exception ex)
        {
            MessageBox.Show("Exception in DoRun()");
        }
    }
}

And here is Form2:

public partial class Form2 : Form
{
    public bool IsClosed { get; private set; }

    public Form2()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        throw new Exception("INTERNAL EXCEPTION");
    }

    protected override void OnClosed(EventArgs e)
    {
        IsClosed = true;
    }
}
+3
source share
5 answers

1.) I would recommend using BackgroundWorker instead of separate threads like this. Your worker will catch the exceptions and pass them as a parameter to the full handler.

2.) ShowDialog() Show() , DoRun() , try/catch ( BackgroundWorker ).

, , , Show(), Invoker, . , , , , . , ShowDialog() ( ).

- :

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // NOTE: I forget the event / method names, these are probably a little wrong.
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += (o, e) =>
        {
            Form2 f = new Form2();
            e.Result = f.ShowDialog();
        };
        worker.DoWorkComplete += (o, e) =>
        { 
            if(e.Error != null)
                MessageBox.Show(string.Format("Caught Error: {0}", ex.Message));

            // else success!
            // use e.Result to figure out the dialog closed result.
        };

        worker.DoWorkAsync();
    }
}

, , , , , .

+2

, ( ShowDialog()), Application_ThreadException, , CatchException Application.ThreadException . ( ).

, :

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException, false);

CatchException . ( Visual Studio .) ( , true ).

Application.ThreadException, [ThreadStatic].

Application.ThreadException += Program.Application_ThreadException;

, .

, SafeThread , , , SafeThread. , .

. , .

+2

:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

:

#if DEBUG
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
#else
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
#endif

, Visual Studio Visual Studio , , , . , Application.ThreadException AppDomain.

. " ...", , , .

+1

try/catch ?

0

, -, . DoRun() - , Form.Show() - , Visual Studio .

, , . Visual Studio , , . Visual Studio - " " - .

, , , - , , , . WinForms , , - , - , - , - .

0

Source: https://habr.com/ru/post/1712228/


All Articles