简体   繁体   English

WPF中的线程异常中止

[英]Thread abort exception in WPF

I am trying to implement loaders in my WPF application. 我正在尝试在WPF应用程序中实现加载程序。 During some heavy operations, the UI thread gets frozen, so I had to implement the loaders using threads. 在执行一些繁重的操作期间,UI线程被冻结,因此我不得不使用线程来实现加载程序。 Each time the loader loads, a new thread is created and this thread gets aborted (manually) when the loader sets off. 每次加载程序加载时,都会创建一个新线程,并且在加载程序启动时该线程将被中止(手动)。 The problem I am facing is that sometimes the application gets crashed giving a ThreadAbortException . 我面临的问题是,有时应用程序会崩溃,给出ThreadAbortException

This is the code to start the loader : 这是启动加载程序的代码:

try
        {
            //if(newWindowThread !=null && !newWindowThread.IsAlive) { }
            newWindowThread = new Thread(new ThreadStart(() =>
            {
                try
                {
                    // Create and show the Window
                    awq = new BusyIndicatorDisguise(BusyMessage);
                    awq.Show(); // <== POINT WHERE THE EXCEPTION IS THROWN
                    //Start the Dispatcher Processing
                    if (!isDispatcherStarted)
                    {
                        var a = Thread.CurrentThread;
                        var b = Dispatcher.CurrentDispatcher;
                        //isDispatcherStarted = true;
                        Dispatcher.Run();
                    }

                }
                catch (ThreadAbortException thEx)
                {

                }
                catch (Exception ex)
                {

                }
            }
            ));
            // Set the apartment state
            newWindowThread.SetApartmentState(ApartmentState.STA);
            // Make the thread a background thread
            newWindowThread.IsBackground = true;
            // Start the thread
            newWindowThread.Start();
        }
        catch (Exception ex)
        {

        }

This code is for stopping the loader : 该代码用于停止加载程序:

if (newWindowThread != null && newWindowThread.IsAlive)
        {          
            newWindowThread.Abort();              
        }

I am not able to catch this exception in my catch block. 我无法在我的catch块中捕获此异常。 Maybe because it is on a different thread. 也许是因为它在不同的线程上。 I want to know how can I avoid the ThreadAbortException 我想知道如何避免ThreadAbortException

You should add a try catch block in the thread that may throw the exception and manage it accordingly to your needs. 您应该在线程中添加一个try catch块,该块可能引发异常并根据需要对其进行管理。

Anyway, as @Josh says in other similar post 无论如何,就像@Josh在其他类似文章中所说的那样

There are much better ways of aborting a thread without using Thread.Abort which not only chaotically interrupts your code at an unpredictable point, it's also not guaranteed to work because if your thread is currently calling out to some unmanaged code, the thread will not abort until control returns to managed code. 有很多更好的方法可以在不使用Thread.Abort的情况下中止线程,它不仅会在无法预测的位置混乱地中断代码,而且还不能保证正常工作,因为如果您的线程当前正在调用某些非托管代码,则该线程不会中止直到控制权返回到托管代码。

It's much better to use some type of synchronization primitive such as aManualResetEvent to act as a flag telling your thread when to exit. 最好使用某种类型的同步原语,例如aManualResetEvent作为标记,告诉您的线程何时退出。 You could even use a boolean field for this purpose which is what the BackgroundWorker does. 您甚至可以为此使用一个布尔字段,这是BackgroundWorker所做的。

If you throw an exception for yourself, forget the Thread.Abort . 如果您为自己抛出异常,请忘记Thread.Abort That's why: 这就是为什么:

  • Throwing an exception is an extremely costly operation. 抛出异常是非常昂贵的操作。 It saves the whole call stack and other useful data for debugging. 它将保存整个调用堆栈和其他有用的数据以进行调试。 In this case all you need is just to set a simple flag. 在这种情况下,您只需要设置一个简单的标志即可。
  • ThreadAbortException is a tricky one. ThreadAbortException是一个棘手的问题。 It is automatically re-thrown at the end of the exception handler block unless you call Thread.ResetAbort in the catch block. 除非您在catch块中调用Thread.ResetAbort ,否则它将在异常处理程序块的末尾自动重新抛出。 But do NOT do that ! 但是不要那样做
  • A ThreadAbortException is an asynchronous exception that means it can occur at any point of your code, which may cause unpredictable results. ThreadAbortException是一个异步异常,这意味着它可以在代码的任何地方发生,可能会导致不可预测的结果。 It is a brute force tool such as the End task button in the Task Manager. 它是一种蛮力工具,例如“任务管理器”中的“ 结束任务”按钮。 Use it only if you cannot rewrite the executed code (3rd party component) and if you are sure that you can unload the remains of the unstable execution environment (it is executed in an AppDomain ). 仅当无法重写已执行的代码(第三方组件)并且确定可以卸载不稳定的执行环境(在AppDomain执行)的其余部分时,才使用它。

Instead, send a cancellation request to your loader (can be a simple bool ), which you should poll regularly during the load operation. 取而代之的是,向您的加载器发送取消请求(可以是一个简单的bool ),您应该在加载操作期间定期轮询该取消请求。 Here is an example how you can do it by using a BackgroundWorker and a volatile field. 是一个示例,如何使用BackgroundWorker和volatile字段来实现。

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

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