1

I have an application that generates random numbers for about 20 seconds and shows the random number on the fly in a label in the screen.

I want to show the numbers in the same label but then slow down the display of the numbers so like 5 seconds before stoping the process, the display of the number should smoothly slow down more and more until it stops in the final number. Like a raffle.

Any clue?

VAAA
  • 14,531
  • 28
  • 130
  • 253
  • 1
    So you are looking for a "slot machine" sort of looks where a bunch of numbers go by, slowing in rate, until one is selected? – Matthew May 13 '13 at 19:01
  • exactly like a slot machine effect!! – VAAA May 13 '13 at 19:01
  • 1
    Just use a Timer() and vary the Interval() as you go. Some basic calculations will tell you how many numbers you should generate at each Interval() to end up with approximately the desired amount of overall time... – Idle_Mind May 13 '13 at 19:05
  • You can use threading. It's not really a high precision timer, but it should work. Take a look at http://msdn.microsoft.com/en-us/library/d00bd51t.aspx http://stackoverflow.com/questions/1068205/pausing-a-method-for-set-of-milliseconds http://www.dotnetperls.com/sleep. – SamiHuutoniemi May 13 '13 at 19:01
  • 1
    If you're using Thread.Sleep you are almost certainly doing something wrong. – Eric Lippert May 13 '13 at 19:02

3 Answers3

12

I can start by telling you what not do to. Do not use Thread.Sleep -- doing so is almost always a "worst practice" and will make your UI unresponsive.

If you use Thread.Sleep on a second thread, as mcl suggests, you won't freeze your UI but you are burning an extremely expensive thread to do very little work.

If you are using C# 4 or earlier then I would create a timer set to tick, say, four times a second. Handle the tick event, and if enough time has passed since the last tick event, change the label. Or, change the interval of the timer each time it ticks.

If you are using C# 5, you can just use await Task.Delay(x):

async void Animate()
{
    int delay = 5;
    for(int i = 1; i < 10; ++i)
    {
       UpdateLabel();
       await Task.Delay(delay);
       delay = delay * 2;
    }
}

So now you start with a 5ms delay, then 10, then 20...

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
2

Here's a working program to get you started. It changes the Text of the Form for 3 seconds quickly, after which it gets slower. That's achieved by using one Timer to start decelerating the Timer which shows the random numbers.

public partial class Form1 : Form
{
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer() { Interval = 10 };
    System.Windows.Forms.Timer timerForStartingSlowDown = new System.Windows.Forms.Timer() { Interval = 3000 };
    bool slow = false;
    Random random = new Random();

    public Form1()
    {
        InitializeComponent();
        timer.Tick += timer_Tick;
        timerForStartingSlowDown.Tick += timerForStartingSlowDown_Tick;
        Shown += Form1_Shown;
    }

    void timerForStartingSlowDown_Tick(object sender, EventArgs e)
    {
        slow = true;
        timerForStartingSlowDown.Enabled = false;
    }

    void Form1_Shown(object sender, EventArgs e)
    {
        timer.Enabled = true;
        timerForStartingSlowDown.Enabled = true;
    }

    void timer_Tick(object sender, EventArgs e)
    {
        if (timer.Interval > 350) timer.Enabled = false;
        else
        {
            if (slow) timer.Interval += 10;
            Text = random.Next(1, 100).ToString();
        }
    }
}
ispiro
  • 26,556
  • 38
  • 136
  • 291
1

Consider generating those numbers on a different thread. You can use BackgroundWorker for that and report the progress as you generate each number. When you begin to reach the end use Thread.Sleep(miliseconds) to "slow" (freez) the BackgroundWorker's job thread that is generating the numbers for a specified amount of miliseconds increasing those miliseconds as you aproach the final number. That should do the trick.

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Set the BackgroundWorker to report progress and use that to "push" the generated number to the UI thread. You can also drag and drop the BackgroundWorker component on your form from the Toolbox.

Mihail Shishkov
  • 14,129
  • 7
  • 48
  • 59