WPF中的线程异常终止
我想在我的WPF
应用程序中实现装载器。在一些繁重的操作中,UI线程被冻结,所以我必须使用线程来实现加载器。每次加载器加载时,都会创建一个新线程,并且在加载器启动时该线程会中止(手动)。我面临的问题是,有时应用程序崩溃给出ThreadAbortException
。WPF中的线程异常终止
这是启动加载器代码:
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)
{
}
此代码是用于停止装载机:
if (newWindowThread != null && newWindowThread.IsAlive)
{
newWindowThread.Abort();
}
我不能够赶上这个例外在我的catch块。也许是因为它在不同的线程上。 我想知道如何避免ThreadAbortException
您应该在线程中添加一个try catch块,以便根据您的需要抛出异常并对其进行管理。
无论如何,@Josh在其他类似的帖子说
有中止线程不使用Thread.Abort的不仅混乱在 不可预测的点打断你的代码 的更好的方法,这也是不保证工作,因为如果 您的线程当前正在调用某些非托管代码,则 线程将不会中止,直到控制返回到托管代码。
使用某种类型的同步原语(如 aManualResetEvent)充当标志,告诉您的线程何时退出,这会更好。 您甚至可以为此使用布尔型字段,这是BackgroundWorker所做的。
我已经在我的线程中放了一个try catch块。无论如何,我之前没有听说过** ManualResetEvent **。将试一试,并会让你知道。 –
如果您为自己抛出异常,则忘记Thread.Abort
。这就是为什么:
- 抛出异常是一个非常昂贵的操作。它可以保存整个调用堆栈和其他有用的数据以进行调试。在这种情况下,你只需要设置一个简单的标志。
-
ThreadAbortException
是一个棘手的问题。除非您在catch
块中调用Thread.ResetAbort
,否则它会自动重新抛出异常处理程序块的末尾。但做不是这样做! - A
ThreadAbortException
是一个异步异常,这意味着它可以发生在您的代码的任何一点,这可能会导致不可预知的结果。这是一个蛮力工具,例如任务管理器中的结束任务按钮。只有当您不能重写已执行的代码(第三方组件)并且您确定可以卸载不稳定执行环境的剩余部分(它在AppDomain
中执行)时才使用它。
取而代之,请向您的加载程序发送取消请求(可以是简单的bool
),您应该在加载操作期间定期轮询。 Here是一个示例,您可以通过使用BackgroundWorker
和易失性字段来完成此操作。
考虑使用CancellationToken而不是中止线程。 – yaakov