AngelicCore
AngelicCore

Reputation: 1453

ProgressBar slowing my code by a factor of ~25 [Async]

I am doing some file iteration and have a progressbar with a max value = number of lines in file(about 1.3 million) for my test scenario.

Before using a progress bar this iteration of the file(line by line) would take about 2 seconds

After using the progress bar and incrementing it once for each line it takes about 50 seconds.

My calls are as follows [MVP - Views - WinForms]

In Presenter:

return Task.Run(() =>
            {
                using (var reader = File.OpenText(FileName))
                {
                    while (!reader.EndOfStream)
                    {
                        var currentLine = reader.ReadLine();
                        _splitterFormView.PerformStep(1);
                        if (currentLine.ToUpper().Contains("BLA"))
                        ...
                    }
                }
            });

In Form:

void PerformStep(int stepValue)
{
    Invoke(new Action(() => { progressBarStatus.Increment(stepValue); }));
}

I've tried with BeginInvoke but there was no difference in runtime.

Am I doing this wrong?

Edit: As I've mentioned, I've tried BeginInvoke - the runtime was the same but it appeared to go much smoother.

You guys are correct - When I think about it I don't know why I went with Max value being the number of lines and doing 1 PerformStep() for every call..might be laziness.

Upvotes: 2

Views: 950

Answers (2)

DiskJunky
DiskJunky

Reputation: 4971

Try to avoid too many updates to the UI as it causes a lot of redrawing to occur on the form. It's the number of redraws that's causing your application to slow down.

If your file has a lot of lines then updating the progress bar for a large number of the lines will redraw the bar without moving it. E.g., if your progress bar is 400 pixels wide but you're updating it 10,000 times, a lot of those redraws are unnecessary.

For example, something a bit like this:

float _previousValue;

void PerformStep(int stepValue, int maximumValue)
{
    var scaledValue = (float)stepValue / (float)maximumValue * 100.0F;
    if (scaledValue != _previousValue)
    {
        BeginInvoke(new Action(() => { progressBarStatus.Increment(stepValue); }));
        _previousValue = scaledValue;
    }
}

Upvotes: 2

mikelegg
mikelegg

Reputation: 1327

There is not much point in updating the progress bar that many times.

Scale the progress par maximum to be a smaller range, e.g. 0-100, and then only invoke the change if the scaled number actially changes.

Upvotes: 2

Related Questions