0

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

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用于通过线路从我的应用程序中运行的 2 个其他进程查询信息。回复可能需要一段时间才能回复。此外,数据可能需要一段时间才能恢复。

我的应用程序主窗口中有一个名为Dashboard. Dashboard上面有一个 DataGrid显示冗长操作的结果。因为它们很长,所以它上面还有一个Button名为 Refresh 的启动进程。而且,因为它可能需要很长时间才能运行,所以我ProgressControl在表单上写了一个名为 a 的 UserControl。这包括一个 Cancel Button,aProgressBar和一个TextBlock可以显示消息的位置。当用户单击 CancelButton时,刷新停止。

以下是一些代码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在前端应用程序中实例化吗?

托尼

4

2 回答 2

2

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

BackendWorker.RunWorkerCompleted += BackendWorker_RunWorkerCompleted;
EocWorker.RunWorkerCompleted += EocWorker_RunWorkerCompleted;
于 2012-05-19T00:11:56.203 回答
0

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

这一切现在都有效!我看到Progress_Changed方法和RunWorkerCompleted方法运行。

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

所以让它成为一个教训:BackgroundWorker必须在 UI 线程上的代码中实例化。

于 2012-05-19T00:26:39.640 回答