简体   繁体   English

捕获线程中的所有异常

[英]Catching all exception in a thread

Let's say I have console application and want to run WPF Window in another thread. 假设我有控制台应用程序,并且想在另一个线程中运行WPF Window 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: 在代码的其他地方,我正在更改一些MainWindow属性,如下所示:

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. 我认为所有的异常将在抛出th线程,该线程内部的的try-catch会赶上他们,但事实并非如此。 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. 如果SomeProperty抛出一个异常,它留下th线程(或从来没有过吧?),直接出现在我的主线程,导致我的应用程序崩溃/退出。

What am I doing wrong? 我究竟做错了什么? Is instance.SomeProperty = "Some value"; instance.SomeProperty = "Some value"; not executing on th thread? 不执行上th线程? How can I execute it on th thread? 我该如何执行它在th线?

There are a couple of events that WPF provides that could help your situation. WPF提供了一些事件可以帮助您解决问题。 First, there's the Application.DispatcherUnhandledException Event : 首先,有Application.DispatcherUnhandledException事件

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. 应用程序针对主UI线程上运行的代码未处理的每个异常引发DispatcherUnhandledException。

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. 如果在后台用户界面(UI)线程(具有自己的Dispatcher的线程)或后台工作线程(没有Dispatcher的线程)上均未处理异常,则该异常不会转发到主UI线程。 Consequently, DispatcherUnhandledException is not raised. 因此,不会引发DispatcherUnhandledException。 In these circumstances, you will need to write code to do the following: 在这种情况下,您将需要编写代码来执行以下操作:

1.Handle exceptions on the background thread. 1.处理后台线程上的异常。

2.Dispatch those exceptions to the main UI thread. 2.将这些异常分配给主UI线程。

3.Rethrow them on the main UI thread without handling them to allow DispatcherUnhandledException to be raised. 3.将它们扔到主UI线程上而不进行处理,以允许引发DispatcherUnhandledException。

Your other option is the AppDomain.UnhandledException Event : 您的另一个选项是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. 请注意,此处理程序仅在您收到Exception时为您提供记录错误的方式...该程序将在之后关闭,因此此程序对您而言并不是那么有用。 From the linked page on MSDN: 从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. 在我提供链接的两页上,还有很多关于未处理的Exception的文章可供阅读...您可能做得比彻底阅读它们还要差。

Try with ContinueWith and finally TaskScheduler.FromCurrentSynchronizationContext() methods. 尝试使用ContinueWith ,最后尝试TaskScheduler.FromCurrentSynchronizationContext()方法。 So you are asserting to come back in the mainThread 所以你断言要回到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! 问候!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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