Reputation: 470
I am trying to report a progress for progress bar in my WPF application, but it seems that my background worker's reportProgress does not fire an event.
Here is my code : -
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();
}
I also tried adding breakpoints on every event methods and debug it but I'm not getting any solution
Upvotes: 0
Views: 522
Reputation: 6820
The problem is that when you call Dispatcher.Invoke
, the code runs on the dispatcher thread, not the background thread. That's probably why it fails to report progress.
You should either:
a) Change your code so it doesn't use a background worker at all
b) Change your background worker so it doesn't run code on the dispatcher thread.
c) If you need to, you can change the background worker so it runs bits and pieces on the dispatcher thread, but not everything. You probably only need to run the UI-related stuff on the dispatcher thread; something like this:
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);
}
}
I'm not sure what addRowstoGrid
does, but it may need to run on the dispatcher thread as well. You may consider just calling it from the constructor instead of from the background thread. The important part is to call ReportProgress
on the background thread.
Also, as a note, fetcher.getNewFiles()
will be called multiple times - once for every iteration of the loop. Is that what you wanted?
Upvotes: 2