我正在尝试在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();
}
我也尝试在每个事件方法上添加断点并调试它,但我没有得到任何解决方案
答案 0 :(得分:2)
问题在于,当您调用Dispatcher.Invoke
时,代码在调度程序线程上运行,而不是在后台线程上运行。这可能是它未能报告进展的原因。
你应该:
a)更改您的代码,以便它根本不使用后台工作程序
b)更改后台工作程序,使其不在调度程序线程上运行代码。
c)如果需要,可以更改后台工作程序,使其在调度程序线程上运行一些零碎,但不是所有内容。您可能只需要在调度程序线程上运行与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()
将被多次调用 - 每次迭代循环一次。那是你想要的吗?