简体   繁体   中英

Progress bar & background worker

I'm trying to use a progress bar to display on the splash screen of the application.

Though I was surprised that it didn't work simply by calling progressBar.Value = newValue ...

So I did some research and found out that other heavy work could block the UI thread ...

Q1

But what I don't really understand is that if everything is happening on the UI thread, why the progress bar is not refreshing at all ?

Even if I was doing "heavy work" like I/O, while finishing an I/O, I refresh the progress bar ... So shouldn't the progress bar refresh before starting another I/O ???

Q2

Alright, let's now say that I have to use background worker to do the heavy work and UI thread to refresh progress bar.

The heavy work I do is on loading the application. It prepares object that I will be needed later on, and after heavy work, I need to start the application with a new window etc.

When do I do it ?

Do I add a RunWorkerCompleted event handler and put every part of my remaining code of the application in that ?

And then, everything happening in the event handler, is it UI thread or another thread of Background worker ???

Thanks a lot for your help

So as asked, here is some part of my code:

The progress bar in question :

<ProgressBar Name="progressBar" Height="20" Value="0" Maximum="100" Minimum="0" />

And the worker :

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += WorkerOnDoWork;
worker.RunWorkerCompleted += WorkerOnRunWorkerCompleted;
worker.ProgressChanged += SplashManager.onProgress;
worker.RunWorkerAsync();

The SplashManager.onProgress method:

public static void onProgress(object sender, EventArgs e)
{
    screen.setProgress(((ProgressChangedEventArgs)e).ProgressPercentage);
}

And the screen setProgress method:

public void setProgress(double progress)
{
    progressBar.Value = progress;
}

And now I'm having an exception on progressBar.Value = progress :

the calling thread cannot access this object because a different thread owns it

Progress bar control will refresh when it gets message to repaint. But while your slow method is running, messages are not processed.

You can either call Application.DoEvents() after changing progressBar.Value , which will process all waiting messages (which in extreme cases could include clicking on buttons or closing form that you are working with).

Or call (also after changing value):

progressBar.Invalidate();
progressBar.Update();

You could do like how Mykola Kovalchuk suggested. But for heavy work, it is suggested to use BackgroundWorker as it supports cancellation and you can interact with the UI when the thread is active, clicking a cancel button for example.

Q2 :

When do I do it ?

Do I add a RunWorkerCompleted event handler and put every part of my remaining code of the application in that ?

Yes, You can do other useful work while BackgroundWorker is busy, and when RunWorkerCompleted triggers you can call a function to do what you want.

And then, everything happening in the event handler, is it UI thread or another thread of Background worker ???

It does run on the main UI Thread. more information here MSDN .

When using BackgroundWorker , you can use the ProgressChanged event to update the progress bar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM