Reputation: 3013
I'm trying to read a file and display the progress on the screen. It should be displayed on a Progress Bar (progress) and a textbox (progress_text).
This is the code I'm using:
public partial class MainWindow : Window
{
public static List<String> file = new List<String>();
public long currentPosition = 0;
String line;
long length;
public BackgroundWorker worker = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
worker.WorkerReportsProgress = true;
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
}
private void Start(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bg = sender as BackgroundWorker;
Dispatcher.Invoke(() =>
{
progress.Minimum = 0;
progress.Maximum = 100;
FileInfo fi = new FileInfo(upload.Text);
length = fi.Length;
int percent;
using (StreamReader sr = new StreamReader(upload.Text, System.Text.Encoding.ASCII))
{
while (sr.EndOfStream == false)
{
line = sr.ReadLine();
file.Add(line);
currentPosition += line.Count();
percent = (int)(100.0 / length * currentPosition);
bg.ReportProgress(percent);
}
}
});
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progress.Value = e.ProgressPercentage;
progress_text.Text = "reading " + currentPosition + " out of " + length;
}
}
XAML:
<Window x:Class="ProgressBarUploadFile.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20*"/>
<RowDefinition Height="20*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="Select File" FontSize="15" Click="Upload_file"/>
<TextBox x:Name="upload" Grid.Row="0" Grid.Column="1" Text="" />
<Button Grid.Row="1" Grid.Column="0" Content="Start upload" FontSize="15" Click="Start"/>
<ProgressBar Name="progress" Grid.Row="1" Grid.Column="1" />
<TextBlock Name="progress_text" Grid.Row="1" Grid.Column="1" VerticalAlignment="Bottom"/>
</Grid>
When I run it in debug, it seems to be working. But the progress bar and textbox are updated only when the file is read completely.
I followed a few tutorials, such as:
https://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx?f=255&MSPPError=-2147217396
http://www.wpf-tutorial.com/misc-controls/the-progressbar-control/
But I can't figure it out..
I think it's something very small, but I can't find it.
Thank you!
Upvotes: 0
Views: 3219
Reputation: 8786
Your code has this problem:
(int)(a / b) * 100
will calculate a/b
first then convert it to int
and then *100
, so before a
reaches b
, the a/b
will always be 0.*
and (int)(a/b)
will always be 0
so the final value 0*100
will always be 0.
Suddenly when a=b
then (int)(a/b)
become 1
and the final value changed to 100. That is why your progress bar will not be updated until the file is read completely
So, you should use percent = (int)(currentPosition * 100 / length);
Or as @jmc suggested in the comment: use percent = (int)(100.0 / length * currentPosition);
Upvotes: 2
Reputation: 902
Try this code:
private void Start(object sender, RoutedEventArgs e)
{
progress.Minimum = 0;
progress.Maximum = 100;
worker.RunWorkerAsync();
}
BackgroundWorker bg = sender as BackgroundWorker;
FileInfo fi = new FileInfo(@"File");
length = fi.Length;
int percent;
using (StreamReader sr = new StreamReader(@"File", System.Text.Encoding.ASCII))
{
while (sr.EndOfStream == false)
{
line = sr.ReadLine();
file.Add(line);
currentPosition += line.Count();
percent = (int)(currentPosition / length) * 100;
bg.ReportProgress(percent);
Thread.Sleep(100);
}
}
Upvotes: 2