BackgroundWorker:在UserControl之间切换后,已完成事件中的启用/禁用按钮不起作用

时间:2010-10-08 14:11:49

标签: c# .net wpf backgroundworker

我的BackgroundWorker放置在UserControl中时遇到问题。 我的WPF应用程序左侧有一个导航,每个条目都加载了自己的UserControl,用户可以在其中生成PDF文件。

因为创建PDF需要一些时间我已经实现了BackgroundWorker来完成工作,另外我禁用了一些按钮并显示了进度条。 在RunWorkerCompleted事件中,我重置了按钮的状态并隐藏了进度条。

所有这一切都运作良好,尽管有一种情况: 当PDF创建正在运行时,用户可以在UserControls之间切换,如果他返回到他开始作业的控件,控件应该显示进度条和按钮为禁用。 为此,我向UserControl添加了一个变量(isProcessing)。

我有这个控件的构造函数:

        // Check if a current process is running, if so: handle button/progressbar visibility
        if (_isProcessing)
        {
            _stkProgressBar.Visibility = Visibility.Visible;
            progressBar1.IsIndeterminate = true;

            // Disabling the buttons here is just working with a hack in
            // the "Button_IsEnabledChanged" event.
            btnDaten.IsEnabled = false;
            btnBericht.IsEnabled = false;
            this.Cursor = Cursors.Wait;
        }
        else
        {
            _stkProgressBar.Visibility = Visibility.Hidden;
        }

启用/禁用按钮只是因为这种肮脏的黑客行为而起作用:

    private void btnDaten_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        //HACK: We want to disable the report buttons if a report execution is running.
        //      Disabling the buttons in the Load Event of the control isn't working
        if (_isProcessing && (bool)e.NewValue)
        {
            btnDaten.IsEnabled = false;
            btnBericht.IsEnabled = false;
        }
    }

现在,如果作业正在运行且用户在控件之间切换,则处理控件的状态正常。但是如果作业结束且PDF准备就绪,则无法启用按钮,并且进度条也保持可见。代码放在RunWorkerCompleted事件中:

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // This is not working if the user switches between the controls
        _isProcessing = false;
        this.Cursor = Cursors.Arrow;
        _stkProgressBar.Visibility = Visibility.Hidden;
        btnDaten.IsEnabled = true;
        btnBericht.IsEnabled = true;
    }

我调试了它,看到按钮得到了正确的输入,因此应该启用,但没有任何反应。如果用户停留在他开始作业的控件中,则会正确重置按钮和进度条的状态。

1 个答案:

答案 0 :(得分:3)

是的,用户控件之间的切换是这里的问题。当您切换并切换回来时,您将创建一个控件实例。这将创建BackgroundWorker的 new 实例。其中有一个RunWorkerCompleted事件处理程序与实际运行的BGW无关。

您的代码中还有另一个错误,当原始BGW实例完成作业并设置(现在不可见)控件属性时,这会导致程序使用ObjectDisposedException崩溃。当您在用户控件之间切换时,您忘记在用户控件上调用Dispose()。不太确定如何在WPF中完成,但在winforms中这是一个不可插拔的漏洞。

只要你想支持切换,你就会有不同的看法。 BGW实例需要与用户控件实例分开,以便它可以在交换机中存活。相当痛苦,你必须在创建和处理控件时连接和取消事件,你肯定需要覆盖Dispose()方法而不要忘记调用它。如果你只允许它一次一个地运行它所做的工作,那么使BGW静态是可以防御的。这应该是正常的。堆叠用户控件以便您只创建一次是Q& D修复。