c# - 为什么 BackgroundWorker 总是很忙?

标签 c# wpf backgroundworker dispatcher dispatch

我在 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/

相关文章:

c# - 如何从内容页重新绑定(bind)母版页内的中继器?

wpf - 如何将 WPF 命令绑定(bind)到 MouseEnter 事件?

wpf - 颜色样式文本 block

C# : Method is being called twice in a row

python - 从 CGI 在后台运行 python 脚本

c# - 上传xml文件进度条

c# - 嵌套的 Try 和 Catch block

c# - 如何在C#中进行相互认证?

C# 反射 : Get info for all members of class and base classes

.net - WPF中的动画宽度到实际宽度?