Derorrist
Derorrist

Reputation: 3013

Progress Bar not updating using BackgroundWorker

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

Answers (2)

Bolu
Bolu

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

lerner1225
lerner1225

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

Related Questions