我的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;
}
我调试了它,看到按钮得到了正确的输入,因此应该启用,但没有任何反应。如果用户停留在他开始作业的控件中,则会正确重置按钮和进度条的状态。
答案 0 :(得分:3)
是的,用户控件之间的切换是这里的问题。当您切换并切换回来时,您将创建一个新控件实例。这将创建BackgroundWorker的 new 实例。其中有一个RunWorkerCompleted事件处理程序与实际运行的BGW无关。
您的代码中还有另一个错误,当原始BGW实例完成作业并设置(现在不可见)控件属性时,这会导致程序使用ObjectDisposedException崩溃。当您在用户控件之间切换时,您忘记在用户控件上调用Dispose()。不太确定如何在WPF中完成,但在winforms中这是一个不可插拔的漏洞。
只要你想支持切换,你就会有不同的看法。 BGW实例需要与用户控件实例分开,以便它可以在交换机中存活。相当痛苦,你必须在创建和处理控件时连接和取消事件,你肯定需要覆盖Dispose()方法而不要忘记调用它。如果你只允许它一次一个地运行它所做的工作,那么使BGW静态是可以防御的。这应该是正常的。堆叠用户控件以便您只创建一次是Q& D修复。