1

I have a UI design question.

I would like to exit the application when it encounter an exception on a non-UI thread.

Basically, the event goes like this:

Main Form -> ShowDialog of sub WinForm (MainThread)-> Starts a background thread (WorkerThread) -> Exception occurs -> Show an ErrorForm (WorkerThread)

When the user click Exit button on the ErrorForm, i want to exit the entire application. However, doing the following call doesn't work.

Invoker.Invoke((Action)(() => { Application.Exit(); }), null);

The Invoker reference to the main form SynchronizedContext. However, since the MainThread is still waiting for the subWinForm to return its control, it probably can't handle the Application.Exit().

What would be a better design to handle exception that is thrown by a background worker thread?

dsum
  • 1,433
  • 1
  • 14
  • 29
  • 1
    You are helping too much, the CLR already knows how to terminate the program when there's an unhandled exception in a worker thread. Just implement an event handler for the AppDomain.CurrentDomain.UnhandledException event to show the user what went wrong. – Hans Passant Jul 29 '11 at 00:47
  • We actual implmeneted CurrentDomain.UnhandledException and Application.ThreadException. However, these two exception handlers are only for the last resort where we know that there is no way to recover from the application. In my case, I want to give the user option to continue (if the exception is not fatal), restart, or exit. i.e. Application.Restart(). The strange thing is back in .NET 2.0 (awhile ago), these features were was working. I don't think the .NET framework has changed much, probably some architecture in my application was changed causing this feature to fail now. – dsum Jul 29 '11 at 21:59
  • Hmm, what fanciful world do you live in that can pretend an unhandled exception didn't alter the program state irreparably? If the thread knew how to do deal with an exception it would have caught and handled it. – Hans Passant Jul 29 '11 at 22:06
  • The exception is an handled one. However, depending on the type of exception, user are given different option on what they want to do. The UnhandledException are the last barrier where we capture the exception information and force the user to exit the application. The original idea is that we have a general abstracted way to handle exception in the application. It is possible that this design philosophy is a bad one. – dsum Jul 29 '11 at 22:35

2 Answers2

2

Cancel the background worker and send an argument to the BackgroundWorker RunWorkerCompletedEvent to identify there is an exception. After that call the Application.Exit() from there would be fine.

Community
  • 1
  • 1
CharithJ
  • 46,289
  • 20
  • 116
  • 131
  • Just want to be clear, it isn't a BackgroundWorker, it is a System.Thread or System.Thread.Task that we were using. The BackgroundWorker.RunWorkerCompletedEvent sounds interesting. Do you know if the RunWorkCompletedEvent is called using the Main UI Thread, or the worker thread? – dsum Jul 29 '11 at 22:06
1

I know that invoking like this works in Silverlight:

Dispatcher.BeginInvoke(() => Application.Exit());

Or if there's no Dispatcher for your WinForms classes:

Invoker.BeginInvoke(() => Application.Exit());

You had a lot of extra unnecessary code ((Action), null, unnecessary brackets and parentheses). I don't think it would have stopped it from working correctly, but in any case, it's easier to read like this.

Tim S.
  • 55,448
  • 7
  • 96
  • 122
  • s : Is Dispatcher available for Winforms? – CharithJ Jul 28 '11 at 23:12
  • Dispatcher is added only for Silverlight and WPF. In WinForm, we are stuck with Control.Invoke, and we use Control.InvokeRequired to check if we need to call the on the UI Thread. The WinForm control's synchronizes context has the same idea as the Dispatcher where you can pass a job from one thread to another thread. The Invoker is a property that my team added to reference the UI, so that we can separate the business logic and UI logic. – dsum Jul 29 '11 at 21:54