5

I want to set the handler method for all unhandled exceptions from any threads in my WinForms application. I don't create any application domains by myself.

According to UnhandledException documentation, I need to set UnhandledExceptionMode.ThrowException mode via Application.SetUnhandledExceptionMode method to catch main thread's exceptions too:

In applications that use Windows Forms, unhandled exceptions in the main application thread cause the Application.ThreadException event to be raised. If this event is handled, the default behavior is that the unhandled exception does not terminate the application, although the application is left in an unknown state. In that case, the UnhandledException event is not raised. This behavior can be changed by using the application configuration file, or by using the Application.SetUnhandledExceptionMode method to change the mode to UnhandledExceptionMode.ThrowException before the ThreadException event handler is hooked up. This applies only to the main application thread. The UnhandledException event is raised for unhandled exceptions thrown in other threads

So, the resulting code will look like the following:

    public static void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e)
    {
        // ...
    }

    [STAThread]
    static void Main(string[] args)
    {
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionEventHandler);

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm(pathToCheck));
    }

Is it ok? Will it catch all unhandled exceptions from any threads (including the main thread, UI thread and all threads created by Task class)? Did I understand the documentation correctly?

Yes, I saw questions like this here, but I don't understand why should I also use the following code:

Application.ThreadException += new     
  ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
Community
  • 1
  • 1
FrozenHeart
  • 19,844
  • 33
  • 126
  • 242
  • 1
    See [this answer](http://stackoverflow.com/a/6115595/43846) for why you want to handle ThreadException as well. – stuartd Sep 04 '15 at 09:10
  • @stuartd According to this link, I can force UI thread exceptions via `SetUnhandledExceptionMode` method too, so I don't really need to specify `ThreadException` handler. Am I right? – FrozenHeart Sep 04 '15 at 09:22
  • there can be exceptions due to third party libraries, so its always advised to handle ThreadException. – A G Sep 04 '15 at 10:01
  • No, the default handler for ThreadException was a half-decent idea 13 years ago to give programmers new to .NET a shot at dealing with exceptions and not die trying. Those days are over, expecting the user to spin the wheel of fortune in the ugly dialog is quite unreasonable today. – Hans Passant Sep 04 '15 at 11:21
  • @Hans Passant So I don't need to worry about `ThreadException` at all? – FrozenHeart Sep 04 '15 at 12:58

1 Answers1

5

You should subscribe both events. Note that even this will not catch automatically everything from other threads. For example, when delegates are invoked asynchronously, the exception will be propagated to the caller thread only when EndInvoke is called.

    [STAThread]
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.UnhandledException +=
            (sender, args) => HandleUnhandledException(args.ExceptionObject as Exception);
        Application.ThreadException +=
            (sender, args) => HandleUnhandledException(args.Exception);
    }

    static void HandleUnhandledException(Exception e)
    {
        // show report sender and close the app or whatever
    }
Dmitry Kazakov
  • 1,639
  • 3
  • 27
  • 47
György Kőszeg
  • 17,093
  • 6
  • 37
  • 65
  • "You should subscribe both events" -- why? "the exception will be propagated to the caller thread only when EndInvoke is called" -- and what if I don't call `EndInvoke` method explicitly at all? – FrozenHeart Sep 04 '15 at 12:54
  • *Why*: Because they catch exceptions from different sources. See https://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception%28v=vs.110%29.aspx *EndInvoke*: Normally you should not worry about that, in an already working application `BeingInvoke` and `EndInvoke` are always called in pairs. Otherwise, the result of the call would be lost, too. See http://stackoverflow.com/questions/7492741/c-sharp-asynchronous-call-without-endinvoke – György Kőszeg Sep 04 '15 at 13:07
  • Should I set `ThreadException` in the `main` method only? Will it enable this feature to all future tasks and threads? – FrozenHeart Sep 04 '15 at 14:29
  • If you don't use multiple `AppDomain`s, then yes, it is enough. – György Kőszeg Sep 04 '15 at 14:31
  • If use *multiple AppDomains*, where I put `Application.ThreadException` ? – Kiquenet Jan 31 '19 at 09:18
  • @Kiquenet: Unless you create forms also in the child domain you do not need to subscribe this event. Otherwise, you can subscribe it in the entry point of your domain just like the other event. On the other hand, handling `AppDomain.UnhandledException` can be always a good idea. The handler in a domain can notify the host domain about the unhandled exception and maybe should even unload the crashed domain. – György Kőszeg Jan 31 '19 at 16:55