我在 WPF 应用程序的后台工作人员中发现了一些奇怪的东西。
我现在想要完成的是等到 BW 完成后启动另一个线程。
检查以下代码:
if (bw.IsBusy)
{
bw.CancelAsync();
System.Threading.ThreadStart WaitThread =
new System.Threading.ThreadStart(delegate() {
while (bw.IsBusy)
{
System.Threading.Thread.Sleep(100);
}
bw.RunWorkerAsync();
});
System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
WaitThread); // if I remove this line, bw fires RunWorkerAsyncEvent
}
else
{
bw.RunWorkerAsync();
}
请注意,我添加了一个 Dispatcher.Invoke 以等待 bw 不忙,但如果我调用它并且从不触发 RunWorkerAsyncCompleted
事件,则所有时间都很忙。虽然,如果我删除该行,则会触发事件,这真的很奇怪。
我如何才能等到 bw 完成?
最佳答案
这就是所谓的“死锁”,一个非常常见的线程问题。在 RunWorkerCompleted 事件运行之前,BGW 无法停止忙碌。该事件在您应用程序的主线程上运行,它只能在您的主线程不忙于做其他事情时运行。它必须处于空闲状态,在调度程序循环内运行。
但是您的主线程并没有空闲,它卡在 while() 循环中等待 IsBusy 返回 false。因此事件永远不会运行,因为主线程正忙于等待 BGW 完成,BGW 无法完成,因为主线程永远不会空闲。 “致命的拥抱”,又名僵局。
您必须以不同的方式执行此操作,您不能等待。比如说创建另一个 BGW 实例。或者将等待后的代码移动到 RunWorkerCompleted 事件处理程序中。如果它被激活,比方说,一个按钮的 Click 事件,那么一定要在调用 RunWorkerAsync() 时禁用该按钮,然后在 RunWorkerCompleted 中重新启用它。
关于c# - 为什么 BackgroundWorker 总是很忙?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14430979/