简体   繁体   中英

Catching all exception in a thread

Let's say I have console application and want to run WPF Window in another thread. This is my solution so far:

var th = new Thread(() =>
{
    try
    {
        System.Windows.Application currentApp = new System.Windows.Application();
        instance = new App.MainWindow(); //instance is declared somewhere else

        currentApp.Run(instance);
    }
    catch (Exception ex)
    {
        //log exception
    }
});
th.SetApartmentState(ApartmentState.STA);
th.Start();

Somewhere else in the code I am changing some MainWindow property like this:

instance.Dispatcher.Invoke(() =>
{
    instance.SomeProperty = "Some value";
});

Everything works well, except for the exceptions. I thought that all exceptions will be thrown on th thread, and that try-catch inside the thread would catch them, but that is not the case. If SomeProperty throws an exception, it leaves th thread (or never was in it?) and appears directly in my main thread, causing my application to crash/exit.

What am I doing wrong? Is instance.SomeProperty = "Some value"; not executing on th thread? How can I execute it on th thread?

There are a couple of events that WPF provides that could help your situation. First, there's the Application.DispatcherUnhandledException Event :

private void App_DispatcherUnhandledException(object sender, 
    DispatcherUnhandledExceptionEventArgs e)
{
    // An unhandled Exception occurred!

    // Prevent default unhandled exception processing
    e.Handled = true;
}

From the linked page:

DispatcherUnhandledException is raised by an Application for each exception that is unhandled by code running on the main UI thread.

If an exception is not handled on either a background user interface (UI) thread (a thread with its own Dispatcher) or a background worker thread (a thread without a Dispatcher), the exception is not forwarded to the main UI thread. Consequently, DispatcherUnhandledException is not raised. In these circumstances, you will need to write code to do the following:

1.Handle exceptions on the background thread.

2.Dispatch those exceptions to the main UI thread.

3.Rethrow them on the main UI thread without handling them to allow DispatcherUnhandledException to be raised.

Your other option is the AppDomain.UnhandledException Event :

private void UnhandledExceptions(object sender, UnhandledExceptionEventArgs e)
{
    // An unhandled Exception occurred!
    if (e.IsTerminating)
    {
        // The RunTime is terminating now, so log some error details
    }
}

Please note that this handler just provides a way for you to log errors when it receives an Exception ... the program will close afterwards, so maybe this one is not so useful for you. From the linked page on MSDN:

This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled.

There is plenty more to read regarding unhandled Exception s on the two pages that I provided links for... you could do worse than to read them both thoroughly.

Try with ContinueWith and finally TaskScheduler.FromCurrentSynchronizationContext() methods. So you are asserting to come back in the mainThread

Debug.WriteLine("command execute on {0}", Thread.CurrentThread.ManagedThreadId);

Task.Factory.StartNew(() =>
{
   Debug.WriteLine("executing on {0}", Thread.CurrentThread.ManagedThreadId);
   Thread.Sleep(1000);
})
  .ContinueWith(t =>
{
  Debug.WriteLine("task finished on {0}", Thread.CurrentThread.ManagedThreadId);
}, TaskScheduler.FromCurrentSynchronizationContext());

Hope helps. Greetings!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM