后台Worker ReportProgress方法不触发ProgressChanged事件
本文关键字:ProgressChanged 事件 Worker ReportProgress 方法 后台 | 更新日期: 2023-09-27 17:49:30
我试图在WPF应用程序中报告进度条的进度,但似乎我的后台工作人员的reportProgress没有触发事件。
下面是我的代码:-XAML
<Window x:Class="nk_Image_Converter.DynamicControls.ProgressBarWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ProgressBarWindow" Height="100" Width="500" BorderThickness="0" WindowStyle="None" ResizeMode="NoResize" Background="#d4dce6" Loaded="Window_Loaded" >
<Window.Effect>
<DropShadowEffect Opacity="0.4"/>
</Window.Effect>
<Border BorderBrush="CadetBlue" BorderThickness="3,0,3,3">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="CadetBlue"></Grid>
<Grid Grid.Row="1" Background="Transparent">
<Label x:Name="Message" Content="Please Wait..." Margin="42,15"/>
<ProgressBar x:Name="Progressbar" Width="400" Height="25" Margin="47,38,47,14" Foreground="CadetBlue" BorderBrush="CadetBlue" BorderThickness="2"></ProgressBar>
</Grid>
</Grid>
</Border>
c# public partial class ProgressBarWindow : Window
{
private double _progressCounter = 0;
private double _progress = 0;
private BackgroundWorker backgroundWorker = new BackgroundWorker();
public ProgressBarWindow()
{
InitializeComponent();
this.Left = Application.Current.MainWindow.Left + 250;
this.Top = Application.Current.MainWindow.Top + 200;
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
this.Progressbar.Value = 0;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
this.Dispatcher.Invoke((Action)(() =>
{
this._progress = 0;
addRowstoGrid();
_progressCounter = (100 / ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count);
for (int i = 0; i < ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count; i++)
{
Thread.Sleep(10);
DynamicControls.ImageButton b = new DynamicControls.ImageButton();
((MainWindow)Application.Current.MainWindow)._imageContainer.Height = ((((MainWindow)Application.Current.MainWindow).row + 1) * 125);
((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Height = ((MainWindow)Application.Current.MainWindow)._imageContainer.Height;
Grid.SetRow(b, ((MainWindow)Application.Current.MainWindow).row);
Grid.SetColumn(b, ((MainWindow)Application.Current.MainWindow).col++);
if ((((MainWindow)Application.Current.MainWindow).col + 1) % 5 == 0 && (((MainWindow)Application.Current.MainWindow).col + 1) >= 5)
{
((MainWindow)Application.Current.MainWindow).col = 0;
++((MainWindow)Application.Current.MainWindow).row;
}
((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Children.Add(b);
if (_progressCounter < 99)
this._progress += _progressCounter;
if (_progress > 100)
_progress = 100;
this._progress += ((_progressCounter + _progress) <= 100) ? _progressCounter : 100;
(sender as BackgroundWorker).ReportProgress((int)this._progress, this._progress);
}
}));
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.Progressbar.Value = (double)e.UserState;
}
public void showDialog()
{
ShowDialog();
}
我还尝试在每个事件方法上添加断点并调试它,但我没有得到任何解决方案
问题是,当您调用Dispatcher.Invoke
时,代码运行在调度程序线程上,而不是后台线程上。这可能就是它不能报告进度的原因。
你应该:
a)修改你的代码,使它根本不使用后台工作器b)改变你的后台工作线程,这样它就不会在调度线程上运行代码。
c)如果你需要,你可以改变后台工作线程,让它在调度线程上运行一些片段,但不是全部。你可能只需要在dispatcher线程上运行ui相关的东西;像这样:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
this._progress = 0;
addRowstoGrid();
_progressCounter = (100 / ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count);
for (int i = 0; i < ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count; i++)
{
Thread.Sleep(10);
this.Dispatcher.Invoke((Action)(() =>
{
DynamicControls.ImageButton b = new DynamicControls.ImageButton();
((MainWindow)Application.Current.MainWindow)._imageContainer.Height = ((((MainWindow)Application.Current.MainWindow).row + 1) * 125);
((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Height = ((MainWindow)Application.Current.MainWindow)._imageContainer.Height;
Grid.SetRow(b, ((MainWindow)Application.Current.MainWindow).row);
Grid.SetColumn(b, ((MainWindow)Application.Current.MainWindow).col++);
if ((((MainWindow)Application.Current.MainWindow).col + 1) % 5 == 0 && (((MainWindow)Application.Current.MainWindow).col + 1) >= 5)
{
((MainWindow)Application.Current.MainWindow).col = 0;
++((MainWindow)Application.Current.MainWindow).row;
}
((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Children.Add(b);
}));
if (_progressCounter < 99)
this._progress += _progressCounter;
if (_progress > 100)
_progress = 100;
this._progress += ((_progressCounter + _progress) <= 100) ? _progressCounter : 100;
(sender as BackgroundWorker).ReportProgress((int)this._progress, this._progress);
}
}
我不确定addRowstoGrid
做什么,但它可能需要在调度线程上运行。您可以考虑从构造函数而不是从后台线程调用它。重要的部分是在后台线程上调用ReportProgress
。
另外,需要注意的是,fetcher.getNewFiles()
将被调用多次—在循环的每次迭代中调用一次。这是你想要的吗?