Sean Anderson
Sean Anderson

Reputation: 29301

ToolStripProgressBar doesn't repaint when sleeping immediately afterwards

I have only a little experience with threading in WinForms. I am trying to set a progress bar to 100, sleep for 2 seconds, and then hide the progress bar.

I have:

public void ProgressBarTimerStop()
{
    if (!AnyWorkersBusy())
    {
        if (InvokeRequired)
        {
            Invoke((MethodInvoker)delegate
            {
                ProgressBarTimer.Stop();
                Thread.Sleep(1000);
                Application.DoEvents();
                Thread.Sleep(1000);
                StatusToolStripProgressBar.Visible = false;
                StatusToolStripProgressBar.Value = StatusToolStripProgressBar.Minimum;
            });
        }
        else
        {
            ProgressBarTimer.Stop();
            StatusToolStripProgressBar.Value = StatusToolStripProgressBar.Maximum;
            Thread.Sleep(1000);
            Application.DoEvents();
            Thread.Sleep(1000);
            StatusToolStripProgressBar.Visible = false;
            StatusToolStripProgressBar.Value = StatusToolStripProgressBar.Minimum;
        }
    }
}

For the current problem I am experiencing InvokeRequired is false.

When I call the line:

StatusToolStripProgressBar.Value = StatusToolStripProgressBar.Maximum;

my watch window shows the value as set, but the GUI has not updated to reflect this. If I immediately sleep for a full two seconds the GUI does not update before sleeping.

If I call Application.DoEvents() without calling sleep beforehand -- it appears to do nothing.

If I sleep, then call DoEvents -- the GUI updates, and then I go back to sleep. This is correct, but I feel like my code is heinous.

Am I misunderstanding a key concept here?

EDIT: ProgressBarTimerStop is called only through "RunWorkerCompleted" event handlers.

I tried this, but it had no effect:

StatusToolStripProgressBar.GetCurrentParent().Refresh();

Upvotes: 1

Views: 2756

Answers (2)

Sercan
Sercan

Reputation: 327

Call StatusToolStripProgressBar.ProgressBar.Refresh(); on every step. ProgressBar property of ToolStripProgressBar is hidden and it may not be shown in intellisense list.

Upvotes: 0

Kendall Frey
Kendall Frey

Reputation: 44336

The 'key concept' that you are missing is that updating the progress bar's value does not immediately tell the progress bar to redraw itself.

When you update the progress bar, the GUI thread repaints the progress bar on the next window repaint. This only happens when the GUI thread becomes free to do so. Normally this happens when the window receives a paint message from the operating system. This should be picked up by Application.DoEvents, but it could be that the message isn't queued quickly enough to be picked up by DoEvents. You may be able to force it to with a Refresh call.

Upvotes: 1

Related Questions