How to Handle Unhandled Exceptions in C#

Architecturecexceptionsfail-fastnet

What is best practice when a unhandled exceptions occurs in a desktop application?

I was thinking about to show a message to the user, so that he can contact support. I would recommend to the user to restart the application, but not force it. Similar to what is discussed here: ux.stackexchange.com – What's the best way to handle unexpected application errors?

The project is a .NET WPF application, so the described proposal could look like this (Note that this is a simplified example. Probably it would make sense to hide the exception details until the user click on "Show Details" and provide some functionality to easily report the error):

public partial class App : Application
{
    public App()
    {
        DispatcherUnhandledException += OnDispatcherUnhandledException;
    }

    private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
    {
        LogError(e.Exception);
        MessageBoxResult result = MessageBox.Show(
             $"Please help us fix it and contact support@example.com. Exception details: {e.Exception}" +
                        "We recommend to restart the application. " +
                        "Do you want to stop the application now? (Warning: Unsaved data gets lost).", 
            "Unexpected error occured.", MessageBoxButton.YesNo);

        // Setting 'Handled' to 'true' will prevent the application from terminating.
        e.Handled = result == MessageBoxResult.No;
    }

    private void LogError(Exception ex)
    {
        // Log to a log file...
    }
}

In the implementation (Commands of ViewModels or event handler of external events) I would then only catch the specific exogenous exception and let all other exceptions (boneheaded and unknown exceptions) bubble up to the "Last resort handler" described above. For a definition of boneheaded and exogenous exceptions have a look at: Eric Lippert – Vexing exceptions

Does it make sense to let the user decide if the application should be terminated?
When the application is terminated, then you for sure have no inconsistent state… On the other hand the user may loose unsaved data or is not able to stop any started external process anymore until the application is restarted.

Or is the decision if you should terminate the application on unhandled exceptions depending of the type of application you are writting? Is it just a trade off between "robustness" vs. "correctness" like described in Code Complete, Second Edition

To give you some context what kind of application we are talking about:
The application is mainly used to control chemical lab instruments and show the measured results to the user. To do so the WPF applications communicates with some services (local and remote services). The WPF application does not communicate directly with the instruments.

Best Answer

You have to expect your program to terminate for more reasons than just an unhandled exception anyway, like a power failure, or a different background process which crashes the whole system. Therefore I would recommend to terminate and restart the application, but with some measures to mitigate the consequences of such a restart and minimize the possible data loss.

Start with analysing the following points:

  • How much data can actually get lost in case of a program termination?

  • How severe is such a loss really for the user? Can the lost data reconstructed in less than 5 minutes, or are we talking about losing a days work?

  • How much effort is it to implement some "intermediate backup" strategy? Don't rule this out because "the user would have to enter a change reason" on a regular save operation, as you wrote in a comment. Better think of something like a temporary file or state, which may be reloaded after a program crash automatically. Many types of productivity software does this (for example MS Office and LibreOffice both have an "autosave" feature and crash recovery).

  • In case data was wrong or corrupted, can the user see this easily (maybe after a restart of the program)? If yes, you may offer an option to let the user save the data (with some small chance it is corrupted), then force a restart, reload it and let the user check if the data looks fine. Make sure not to overwrite the last version that was saved regularly (instead write to a temporary location/file) to avoid corrupting the old version.

If such an "intermediate backup" strategy is a sensible option depends ultimately on the application and its architecture, and on the nature and structure of the data involved. But if the user will loose less than 10 minutes of work, and such a crash happens once a week or even more seldom, I would probably not invest too much thought into this.

Related Topic