1

See the code at the bottom of this post. It's supposed to add "3" to the listbox, then "2" a second later, then "1" a second later and then run the main code of the program. However, once I execute the program it just stays blank 3 seconds long, after which all 3, 2, and 1 are shown, after which all the code directly starts. I want to visually see every number show up with a one second delay. How do I do this?

private void Main()
        {
            countdown();
            //Main Code
        }

private void countdown()
        {
            listBox1.Items.Clear();
            listBox1.Items.Add("3");
            System.Threading.Thread.Sleep(1000);
            listBox1.Items.Add("2");
            System.Threading.Thread.Sleep(1000);
            listBox1.Items.Add("1");
            System.Threading.Thread.Sleep(1000);
            listBox1.Items.Clear();
        }
DutchLearner
  • 335
  • 3
  • 13
  • Try to search, Thread.Sleep() blocks the UI thread, use a timer. – CodeCaster Sep 16 '15 at 12:22
  • 3
    Putting the UI thread of a GUI program to sleep is a rather drastic mistake with potentially nasty consequences. Not seeing the update is just a minor mishap, there's worse. Users like responsive programs, no point in making it intentionally slow. Use a Timer for animation. – Hans Passant Sep 16 '15 at 12:29

4 Answers4

8

async / await to the rescue:

private async void OnButtonClick(object sender, EventArgs e)
{
    listBox1.Items.Clear();
    listBox1.Items.Add("3");
    await Task.Delay(1000);

    listBox1.Items.Add("2");
    await Task.Delay(1000);

    listBox1.Items.Add("1");
    await Task.Delay(1000);

    listBox1.Items.Clear();
}
Oliver
  • 43,366
  • 8
  • 94
  • 151
5

First: Why isn't anything happening?

The reason is, that you are currently in the UI thread. By doing Thread.Sleep you suspend the very same thread you expect to draw the items you just added.

Second: How to work around this?

As @CodeCaster mentioned, you could use a Timer to do all this. You could also put your code in a Thread and call the Add method by using a Dispatcher or the SynchronizationContext class and it's Send method.

Third: A small hint on the Sleep method.

Usually it should do what you expect it to, but there is no guarantee for that. Calling Sleep means that your thread will be suspended for roughly the amount of time you want it to. See this answer

Community
  • 1
  • 1
Steffen Winkler
  • 2,805
  • 2
  • 35
  • 58
1

You can use a Timer having the interval set to 1000. Start the timer when you want it to raise Tick event. Stop it to stop raising Tick event. Handle the Tick event and run the code in intervals.

But to have a countdown 3-2-1 function using async-await as it's suggested in the other answer is good idea:

private async void countdown()
{
    listBox1.Items.Clear();
    listBox1.Items.Add("3");
    await Task.Delay(1000);
    listBox1.Items.Add("2");
    await Task.Delay(1000);
    listBox1.Items.Add("1");
    await Task.Delay(1000);
    listBox1.Items.Clear();
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
0

Put a listBox1.Refresh(); after every Sleep() call.

You are letting the thread sleep, but the UI does not get repainted automagically.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76