-1

I have written a WinForms application which performs some sort of syncing work. I want it to keep running despite of any occurrence of exceptions so that syncing keeps on going with next attempts. Thus, I have written the app such a way that whenever an exception occurs, it logs the exception stack trace, performs some diagnostics, then logs the diagnostics information and continues with next syncing attempts.

For uncaught exceptions I added Exception handlers for Application.ThreadException and also for AppDomain.CurrentDomain.UnhandledException in my Main() thread:

static void Main(string[] args)
{    
    Application.ThreadException += new ThreadExceptionEventHandler(UIThreadExceptionHandler);
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);


    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new myForm());
}


//exception handlers
 public static void UIThreadExceptionHandler(object sender, ThreadExceptionEventArgs t)
 {
     logger.Fatal("Fatal Windows Forms Error");
     logStackTrace(t.Exception);                    //logs the stack trace with some desired formatting  
     Application.Exit(new CancelEventArgs(true));
 }

 public static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs t) 
 {
     logger.Fatal("Fatal Application Error");
     logStackTrace((Exception)(t.ExceptionObject)); //logs the stack trace with some desired formatting           
     Application.Exit(new CancelEventArgs(true));
 }

I kept my app running for testing and realized that whenever Application.ThreadException is caught, the app correctly logs the string Fatal Windows Forms Error, followed by the exception stack trace and then the application exits.

I dont want the app to exit. I just want that it should log the exception stack trace and continue with next syncing attempt. The exception that is occurring in UI thread is not that severe one, since the same exception also occurred in the other/non-UI threads of the app, but it did not crashed the app (as I can see this in logs). However when the same exception occurs in the UI thread, the app crashes.

Mahesha999
  • 22,693
  • 29
  • 116
  • 189
  • And what is the question? Do you want the app to continue working after an unhandled exception? – Dmitry Apr 18 '14 at 11:42
  • 1
    @Dmitry yess obviously I said that in first paragraph **want it to keep running despite of any occurrence of exceptions** – Mahesha999 Apr 18 '14 at 12:15
  • please will like to know why down votes – Mahesha999 Apr 18 '14 at 12:18
  • 1
    Why do you use Application.Exit(new CancelEventArgs(true)); in UIThreadExceptionHandler? Remove it and the UI will not be closed – Igor Tkachenko Apr 18 '14 at 12:25
  • Oops I think I had some bad information about `Application.ThreadException` and `CancelEventArgs`. let me try this. I thought `true` parameter to `CancelEventArgs` should prevent app from crashing. I think I have read exiting the application was the default behavior of the `Application.ThreadException` and to prevent that I should do `Application.Exit(new CancelEventArgs(true))`; – Mahesha999 Apr 18 '14 at 12:30

2 Answers2

1

As it's windows forms app Application.ThreadException is used for unhanded exception: "This event allows your Windows Forms application to handle otherwise unhandled exceptions that occur in Windows Forms threads. Attach your event handlers to the ThreadException event to deal with these exception" (MSDN)

I think you must expect such behavior as at UIThreadExceptionHandler you have Application.Exit(new CancelEventArgs(true)). Exit methods description: "Informs all message pumps that they must terminate, and then closes all application windows after the messages have been processed." (MSDN)

AppDomain.CurrentDomain.UnhandledException event is used to handle non-UI thread exceptions.

EDIT 1:

AppDomain.CurrentDomain.UnhandledException is specifically designed to log an exception before the system will inform a user and terminates the process. You can not prevent terminating the process (unless you are using Net 1.1).

Application.ThreadException + UnhandledExceptionMode.CatchException allows you to keep your UI thread alive. But, it's really not a great idea. It's much better to enclose error prone code in try-catch blocks instead.

Thus if you want to catch exceptions coming from thread and keep your application alive, you have to do it inside using try-catch block.

You haven't issue with UnhandledExceptionHandler, because it's not fired at all, I suppose.

Igor Tkachenko
  • 1,120
  • 7
  • 17
  • So I should just remove `Application.Exit(new CancelEventArgs(true));` to prevent app from exiting after `Fatal Error`? I thought `true` parameter to `CancelEventArgs` should prevent app from crashing. I think I have read exiting the application was the default behavior of the `Application.ThreadException` and to prevent that I should do `Application.Exit(new CancelEventArgs(true));` – Mahesha999 Apr 18 '14 at 12:26
  • Yes, you should remove this line of code. UI will not be closed. – Igor Tkachenko Apr 18 '14 at 12:27
  • Just made some changes to above comments, please clear me out – Mahesha999 Apr 18 '14 at 12:28
0

Windows Forms isn't really designed for a scenario where an application needs to run indefinitely. As you've experienced, by the time you've intercepted certain exceptions, your application is already being sucked into a black hole and you can't stop your application dying.

I think a better approach is to use a Windows service that has two threads: a foreground monitor thread and a background worker thread (use the BackgroundWorker type). The worker thread is where your sychronisation work happens. When the worker thread dies due to an unhandled exception, the monitor thread logs the exception and restarts the worker thread.

If the situation is nasty enough that the monitor thread dies as well (eg OutOfMemoryException or ExecutionEngineException), then the service itself will die. But you can set the service control manager to restart the service in that event.

If you need some sort of user interactivity, you can also create a Windows Forms application that talks to the your new service and starts/stops it.

HTTP 410
  • 17,300
  • 12
  • 76
  • 127
  • But now converting WinForms to service will need considerable revamp. And yes I need user interactivity. I will also like to know how to have UI for windows service. But for that I should write another question. But can u just note the approaches for tying UI to win service. I guess Registries is one whats other? – Mahesha999 Apr 18 '14 at 12:18
  • Also can I do some trick here. In fact I thought, `CancelEventArgs(true)` should do the trick, but it seems it doesnt. Also the exception that is occuring is not that severe one as I can see in logs, since this exception is also occurring in other/non-UI threads, but they dont crash the app. But when it appears in UI thread, app crashes – Mahesha999 Apr 18 '14 at 12:20