C# Windows Form is Busy


There are two very common ways of telling the user that your application is busy. One is to show a progress bar that gets updated based on the progress getting done, and another is to show the “Waiting” cursor while the application is doing work.

Waiting Cursor

To show the user the Waiting cursor while your program is busy, all you have to do is to set the current cursor to the Waiting cursor before your code runs, then set it back to an arrow after your code completes.

Cursor.Current = Cursors.WaitCursor;

//  Your Code

Cursor.Current = Cursors.Default;

Progress Bar

The progress bar is a more user-friendly solution, but in most cases showing the waiting cursor does the job. Here is the simplest way to use a progress bar:

int totalSteps = 10;
for (int i = 1; i <= totalSteps; i++)
{
    //  One chunk of your code

    int progress = i * 100 / totalSteps;
    blocksProgressBar.Value = progress;
}
blocksProgressBar.Value = 0;

Yes, it’s that easy to implement a progress bar that gets updated based on the work done by your app. However, while progress is shown, the user can’t interact with the UI or do any other operation (the UI thread is the single thread doing the work here). To get the multi-threaded behavior, the easiest way is to use a background worker process, as shown below:

So instead of putting your code in the event handler method, you will replace it with a call to start the worker process then move the code to the worker process events.

private void doButton_Click(object sender, EventArgs e)
{
    backgroundWorker.RunWorkerAsync();
}

The worker process will do its work in the DoWork event. To show progress, the code needs to be split into segments and the background worker ReportProgress method needs to be called whenever a segment of code is executed.

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int totalSteps = 10;

    for (int i = 1; i <= totalSteps; i++)
    {
        //  One chunk of your code

        int progress = i * 100 / totalSteps;
        backgroundWorker.ReportProgress(progress);
    }
}

Whenever progress changes, we need to update the value of the progress bar.

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    blocksProgressBar.Value = e.ProgressPercentage;
}

When the worker process is done (progress = 100%), we reset the progress bar.

private void backgroundWorker_Completed(object sender, RunWorkerCompletedEventArgs e)
{
    blocksProgressBar.Value = 0;
}

Below is a Windows Form application that lets you try the concepts explained above, and also shows you how the Marquee progress bar works, which is shockingly harder than the more realistic single-threaded progress bar we’ve discussed above.

Download source and exe from here.

About these ads
  1. Thank You! That is exactly what I was looking for.

    • Mike
    • October 4th, 2011

    How do you tie a progress bar to sql query, returning data into a datagridview? It doesn’t have to be totally accurate, just doing something while the data is loading, then stopping once it has loaded…

  2. Seems like the Marquee style does its work using the UI thread. So then it is logical that your options using System.Threading.Thread.Sleep(milliSecondsToWait); do not work, as you are blocking the UI Thread, not allowing your UI to get updated.

    Nice write up however.

    • yogesh makwana
    • January 18th, 2012

    i want to know how to use marque in c#.net windowform…??????

    • Ankit Baria
    • September 14th, 2012

    Really helpful post. Thanks

  3. “C# Windows Form is Busy The Code Log” was
    in fact a truly awesome post, . Keep publishing and I’ll try to continue to keep reading through! Thanks for your time ,Louie

  4. Hi there! I just would like to give a huge thumbs up for the nice information youve gotten here on this post.
    I might be coming again to your weblog for more soon.

    • Khursheed Fateh
    • May 12th, 2014

    See the modifivations I made to ylour program. Now Timer base progressbar is working.


    private Stopwatch s = new Stopwatch(); // Stopwatch
    private void progressButton2_Click(object sender, EventArgs e)
    {
    showProgress = true;
    timer.Enabled = true;
    timer.Start();

    s.Start(); // start stopwatch in this method

    marqueeProgressBar.Style = ProgressBarStyle.Marquee; // set progressbar style in this method
    }

    private void timer_Tick(object sender, EventArgs e)
    {
    if ( s.Elapsed < TimeSpan.FromSeconds((double)secondsToWaitSpinner2.Value))
    {
    // as long as elapsed time is less then the delay time
    // keep going
    toolStripStatusLabel1.Text = s.Elapsed.ToString(); // show elapsed time
    }
    else
    {
    marqueeProgressBar.Style = ProgressBarStyle.Blocks;
    timer.Stop();
    s.Stop(); // stop stop-watch here
    s.Reset(); // reset stop watch so that when you click again
    // it starts from begining and
    // not from where it stoped last time
    timer.Enabled = false;
    toolStripStatusLabel1.Text = "";
    }
    }

    • Khursheed Fateh
    • May 12th, 2014

    “Before and after” part of your code is not working because it is freezing/stoping UI/Form for specified time. Because for the duration marquee is set Form remain froozen/unresponsive progressbar fails to show. You can see this by commenting last statement of method like this. Now you will see progressbar marquee was started but was unable to update itself because form was not responding during that time.

    private void progressButton_Click(object sender, EventArgs e)
    {
    marqueeProgressBar.Style = ProgressBarStyle.Marquee;

    int milliSecondsToWait = (int)secondsToWaitSpinner.Value * 1000;
    System.Threading.Thread.Sleep(milliSecondsToWait);

    // marqueeProgressBar.Style = ProgressBarStyle.Blocks;
    }

  5. I was curious if you ever considered changing the
    structure of your blog? Its very well written; I love what youve
    got to say. But maybe you could a little more in the way of content so people could
    connect with it better. Youve got an awful lot of text
    for only having one or two images. Maybe yyou could space iit out better?

  6. I’m impressed, I must say. Rarely do I encounter a blog that’s both educative and amusing,
    and let me tell you, you have hit the nail on the head.
    The problem is an issue that not enough men and women are speaking intelligently about.
    Now i’m very happy I came across this during my search for something regarding this.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: