在我的应用程序的业务逻辑层中,我有以下类:
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
吗?
贝
答案 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线程的代码中实例化。