BackgroundWorker不会引发RunWorkerCompleted事件

时间:2012-05-19 00:00:19

标签: wpf backgroundworker

在我的应用程序的业务逻辑层中,我有以下类:

public class EocMonitor : DeviceMonitor {

    public BackgroundWorker BackendWorker { get; set; }

    public BackgroundWorker EocWorker { get; set; }

    public EocMonitor() {
        BackendWorker = new BackgroundWorker {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true
        };
        BackendWorker.DoWork += BackendWorker_DoWork;

        EocWorker = new BackgroundWorker {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true
        };
        EocWorker.DoWork += EocWorker_DoWork;
    }

    private void BackendWorker_DoWork( object sender, DoWorkEventArgs e ) {
        // Does some lengthy operation
    }

    void EocWorker_DoWork( object sender, DoWorkEventArgs e ) {
        // Does some lengthy operation
    }

    public void GetDiagnostics() {
        BackendWorker.RunWorkerAsync( new DiagnosticsInfo() );
            EocWorker.RunWorkerAsync( new DiagnosticsInfo() );
    }

}

public class DiagnosticsInfo {

    public int DataTypeCount { get; set; }

    public int DataTypesProcessed { get; set; }
}

BackgroundWorkers用于通过我的应用程序中运行的其他两个进程通过线路查询信息。回复可能需要一段时间才能回来。此外,数据还需要一段时间才能回来。

我的应用程序主窗口中有一个名为Dashboard的WPF UserControl。 Dashboard上有DataGrid,显示冗长操作的结果。因为它们很长,所以它上面还有一个名为Refresh的Button,可以启动该过程。并且,因为它可能需要很长时间才能运行,所以我在表单上编写了一个名为ProgressControl的UserControl。这包括取消Button,ProgressBar以及可以显示消息的TextBlock。当用户点击取消Button时,刷新停止。

以下是Dashboard的一些代码:

public partial class Dashboard : UserControl {

    public Dashboard() {
        InitializeComponent();
    }

    private Dashboard_Loaded( object sender, RoutedEventArgs e ) {
        if ( !setupProgress && EocMonitor != null ) {
             EocMonitor.BackendWorker.ProgressChanged += BackendWorker_ProgressChanged;
             EocMonitor.BAckendWorker.RunWorkerCompleted += BackendWorker_RunWorkerCompleted;
             EocMonitor.EocWorker.ProgressChkanged += EocWorker_ProgresChanged;
             EocMonitor.EocWorker.RunWorkerCompleted += EocWorker_RunWorkerCompleted;
        }
    }

    private void BackendWorker_ProgressChanged( object sender, ProgressChangedEventArgs e ) {
        DiagnosticsInfo info = e.UserState as DiagnosticsInfo;

        // Other processing to notify the user of the progress
    }

    private void BackendWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) {
        // Processing to do when the back-ground worker is finished
    }

    private void DiagnosticsProgressCtrl_Click( object sender, RoutedEventArgs e ) {
        EocMonitor.BackendWorker.CancelAsync();
        EocMonitor.    EocWorker.CancelAsync();

        DiagnosticsProgressCtrl.Visibility = Visibility.Collapsed;

        e.Handled = true;
    }

    void EocWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) {
        // Processing to do when the back-ground worker is finished
    }

    private void RefreshButton_Click( object sender, RoutedEventArgs e ) {
        DiagnosticsProgressCtrl.Maximum = DiagnosticsProgressCtrl.Minimum = DiagnosticsProgressCtrl.Value = 0.0;

        DiagnosticsProgressCtrl.Visibility = Visibility.Visible;

        backendDataTypeCount   = eocDataTypeCount   = 0;
        backendWorkerCompleted = eocWorkerCompleted = false;

        EocMonitor.GetDiagnostics();

        e.Handled = true;
    }

}

问题是我在DoWork方法中放置了断点并观察它们是否完成运行,但是没有调用RunWorkerCompleted方法。没有错误发生或被抛出。这个东西是EocMonitor类,Dashboard类有两个不同的DLL。这有什么区别吗?据我所知,它不应该,但我不明白为什么完成的事件处理程序没有被调用。我应该在前端应用程序中实例化BackgroundWorkers吗?

2 个答案:

答案 0 :(得分:2)

引发了该事件,但您没有看到它,因为您没有订阅RunWorkerCompleted事件......

BackendWorker.RunWorkerCompleted += BackendWorker_RunWorkerCompleted;
EocWorker.RunWorkerCompleted += EocWorker_RunWorkerCompleted;

答案 1 :(得分:0)

好吧,在我发布上述内容后,我回去改变了一些事情。我现在实例化BackgroundWorker控件中的Dashboard个对象,并将它们传递给EocMonitor的GetDiagnostics方法。 EocMonitor中包含这些对象的属性具有私有设置器,因此使用它们的唯一方法是创建它们。将它们传递给该方法。 Dashboard_Loaded中的代码现在在RefreshButton_Click方法中移动,并在实例化对象之后运行,然后再传递给GetDiagnostics.

现在一切正常!我看到Progress_Changed方法和RunWorkerCompleted方法运行。

它只是打击了我为什么它可能不起作用。在程序的初始化阶段,EocMonitor对象是在非UI线程上创建的。由于它在UI对象中调用方法,因此可能无法调用这些方法。可能会抛出某种无效的操作异常,但是没有地方可以捕获它。

所以,这是一个教训:BackgroundWorker必须在UI线程的代码中实例化。