DividedByZero
DividedByZero

Reputation: 4391

C# progressBar not updating until half progress complete

I am using a dispatcherTimer to update the progressBar's Value:

DispatcherTimer tim = new DispatcherTimer();
tim.Interval = TimeSpan.FromMilliseconds(100);
tim.Tick += delegate
{
    if (valuee < max)
    {
        prog.Value = valuee;
    }
    else
    {
        tim.Stop();
    }
};

And setting the progressBar's maximum value like this:

using (FileStream fs = File.Open(Filename, FileMode.Open))
{
    if (fs.Length > 10485760 && fs.Length <= 209715200)
        prog.Maximum = fs.Length / 1024;
    else if (fs.Length <= 10485760)
        prog.Maximum = fs.Length / 16;
    else if(fs.Length > 209715200)
        prog.Maximum = fs.Length / 1048576;
}

Then increasing the value after every iteration of the for loop:

var Input = File.OpenRead(path);
int Size = MainWindow.prog.Maximum;
for (long i = 0; i < Input.Length; i += Size)
{
    MainWindow.valuee++;
    PasswordEnter.valuee++;
    byte[] chunkData = new byte[chunkSize];
    int bytesRead = 0;
    while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
    {
        if (bytesRead != chunkSize)
        {
            for (int x = bytesRead - 1; x < chunkSize; x++)
            {
                chunkData[x] = 0;
            }
        }
        cryptoStream.Write(chunkData, 0, bytesRead);
    }
}

EDIT: This is how I am calling the AESCryptography class:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (obj, l) => lo.Encrypt(Filename, password.Password, "main");
worker.RunWorkerAsync();

But for some reason the progressBar doesn't update until more than half the iterations are over! what's wrong?

Upvotes: 2

Views: 966

Answers (2)

HABO
HABO

Reputation: 15816

Your looping code opens a file, then inside the for loop increments the progress (valuee). It appears that the while loop reads to end-of-file. The for loop then keeps having the while make sure that it is still at EOF since no new file is opened. (I'm assuming that Input and fsInput are supposed to be the same variable.)

The ReportProgress/ProgressChanged mechanism on the BackgroundWorker thread is a reliable way to handle the cross-thread intricacies of updating the UI from a background worker thread. You can use UserState to pass additional information, e.g. the name of the file currently being processed to display in a label.

Upvotes: 1

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

A DispatcherTimer queues work on the Dispatcher thread, which is WPF UI thread.

This is what MSDN says regarding the execution of the timer:

The DispatcherTimer is reevaluated at the top of every Dispatcher loop. Timers are not guaranteed to execute exactly when the time interval occurs, but they are guaranteed to not execute before the time interval occurs. This is because DispatcherTimer operations are placed on the Dispatcher queue like other operations. When the DispatcherTimer operation executes is dependent on the other jobs in the queue and their priorities.

You're experiencing the lag in the progress timer because you are most likely running a long blocking operation which denies the messageloop of processing different requests.

You have two options:

  1. Move the long running operation to a background thread. I would prefer this approach.

  2. Try using the DispatcherTimer overload which takes a DispatcherPriority and specifying a higher priority. This approach still does not guarantee you'll experience change in performance, but it may help.

Upvotes: 2

Related Questions