Handling static constructor exceptions in a multithreaded application

I have a static class that creates several worker threads in its constructor. If an exception occurs before the workers have been created my Application.ThreadException handler (used to shut the app down if an error not known to be recoverable occurs) triggers normally and everything is fine. Once the first worker thread has been created however in addition to the handler firing I get an "MYAPP has encountered a problem and needs to close. We are sorry for the inconvenience." dialog for MS error reporting.

In this specific instance I can reorder the code to create the threads last (after any resource initialization/access problems that could've triggered an exception) but that's no more than a bandaid to the problem and doesn't give me any information about what's actually going on.

Hopefully I've excised enough code from my app to show what I'm trying to do here.

class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        try
        {
            Application.Run(theForm);
            theForm.Dispose();

        }
        catch (Exception e)
        {
            //doing this to use the same handler here and for Application.ThreadException
            ThreadExceptionEventArgs argsEx = new ThreadExceptionEventArgs(e);
            FatalExceptionHandler(null, argsEx);

        }
        finally
        {
            MyStaticClass.KillThreads();
        }
    }

    public static void FatalExceptionHandler(object sender, System.Threading.ThreadExceptionEventArgs ex)
    {
        Exception e = ex.Exception;
        try
        {
            //lots of stuff to give more useful error messages for known problems
            //and display them in a messagebox.
        }
        // if anything went wrong scraping the exception text for formatting, show the raw value.
        catch
        {
            MessageBox.Show(e.Message);
            return;
        }
        // after showing the MessageBox, close out the app.
        finally
        {
            System.Environment.Exit(1);
        }
    }
}

class MyStaticClass
{
    static MyStaticClass()
    {
        myThread = new Thread(new ThreadStart(SomeMethod));

        //if this exception is thrown everything works normally
        //Throw new Exception("KABOOM");

        myThread.Start();

        //if this exception is thrown a windows error reporting dialog appears 
        //along with the messagebox from program.FatalExcetion handlder             
        //Throw new Exception("KABOOM");
    }


    public void KillThreads()
    {
        //clean up the worker threads
    }
}

Upvotes: 1

Views: 893

Answers (2)

Remus Rusanu
Remus Rusanu

Reputation: 294247

The Application.ThreadException is only raised for UI thread unhandled exceptions (since is part of the Application class). The worker thread unhandled exception event is AppDomain.UnhandledException. When an unhandled exception on an worker thread occurs this event is raise and then the system crash dialog is displayed. The AppDomain.UnhandledException is intended for logging purposes only and there is no documented way to prevent the system crash error dialog from being shown.

Upvotes: 1

Sam Harwell
Sam Harwell

Reputation: 99869

Static constructors are not called at a specific time during application startup. In particular, if you never reference MyStaticClass from another class, it may never be initialized. Since you can't reason about this in any sane way, you should provide a StaticInitialize() method (or similar) for the types with non-trivial code in the static constructor plus cases where the static initialization code really needs to run. Move the code from the static constructor to the static initialization method.

Upvotes: 4

Related Questions