8

I want to wait for 15 seconds, then the control should resume from the next statement.

I don't have anything else to do while waiting (Just waiting).

I know that there is Thread.Sleep(15000). What I don't know is the best method to wait? What are the limitations of this?

The code would be like this:

Method()
{
   statement 1;
   statement 2;
   //WaitFor 15 secs here;
   statement 3;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Naresh
  • 636
  • 2
  • 7
  • 18
  • Thread.Sleep(15000) is fine for C#. For WinForms, WPF or ASP.NET it is a disaster. – H H Aug 24 '09 at 07:31
  • Near-duplicates: http://stackoverflow.com/questions/1091710, http://stackoverflow.com/questions/407130, http://stackoverflow.com/questions/1208103 and http://stackoverflow.com/questions/903688. – Peter Mortensen Aug 24 '09 at 07:54

8 Answers8

13

The disadvantage of Thread.Sleep is if this is called in your GUI thread (the thread that processes GUI events, for example, a button click handler method, or a method called from a button click handler, etc.) then you application will appear to freeze and be nonresponsive for those 15 seconds.

It would be perfectly fine if you had explicetly created a seperate thread and called Thread.Sleep in it, assuming you don't mind that thread not doing anything for 15 seconds.

The alternative would be to create a Timer and start it after stmt 2, and place stmt 3 in the Tick event handler for the timer, and also stop the timer in that handler.

AaronLS
  • 37,329
  • 20
  • 143
  • 202
7

This may not be a direct answer to your question. I would say check whether your process flow is better than checking whether the code is better ;-)

Are you waiting for 15 seconds just to make sure stmt2; is complete? If so then adding an handler, as soon as stmnt 2 is executed, would be a better solution (?)

You can also use a timer to wait. Thread.sleep is a bad design. We have a similar question which talks about the comparison using Thread.sleep and Timer.

Community
  • 1
  • 1
Shoban
  • 22,920
  • 8
  • 63
  • 107
3

Thread.sleep seems a sensible thing to do if there isn't anything else to do while waiting. It puts the thread to sleep for that time so it doesn't use any CPU resources.

jcoder
  • 29,554
  • 19
  • 87
  • 130
  • Yes, any other methods would use CPU, and you don't want that if all you need to do is wait... – awe Aug 24 '09 at 07:19
  • It's particularly useful in Unit tests where you need to simulate time delta. The method can't exit so Thread.Sleep() is less evil in this particular situation. For long time intervals I have faked this by altering the system time. Kind of like putting the computer into a time machine. When the test is done it sets the system time back to normal. – Gareth Farrington Nov 02 '09 at 16:05
3

Try something like the following:

void Method()
{
    console.log('statement 1');
    console.log('statement 2');

    var timer = new System.Threading.Timer(
        o =>   // timer callback
        {
           console.log('statement 2');
        },
        15000, // Delay
        0      // Repeat-interval; 0 for no repeat
    );
}

Syntax is C# 3.0, uses a lambda expression to effectively create a closure around statement #3. With this, you could use any local variables of Method. A thing to note, however, is that with this method, or any other timer-based method...the function will return immediately after creating the timer. The function won't block until the Timer executes. To achieve that, the only thing I can think of is to actually use threads and make Method() block on a signal (i.e. WaitHandle, ResetEvent, etc.) until the timed call on the other thread completes.

jrista
  • 32,447
  • 15
  • 90
  • 130
  • 5
    There's a problem with this example. It won't work reliably, since no reference to the `Timer` object is kept anywhere. Thus, it is subject to garbage collection. The longer your delay, the more likely this will be a problem. From MSDN: *As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.* – Thorarin Aug 24 '09 at 11:18
  • @Thorarin: Ah, good point. I forgot all about that little fact. I'll see if I can correct the example. – jrista Aug 25 '09 at 01:30
  • If you want to dispatch the call back on the UI thread, you should use `System.Windows.Forms.Timer` instead. – Sam Harwell Mar 30 '10 at 23:06
  • stmt1 won't compile. Is this a C# keyword? – Exitos May 01 '14 at 13:54
2

You could always use a timer and then execute code after the set duration. However, if you don't actually have to do anything and just want to wait at a particular point in code, then I think Thread.Sleep(150000); is sufficient. [Edit: spelling]

Tim
  • 736
  • 7
  • 9
1

If you always want to wait for a given time, then Sleep is useful. Obviously you shouldn't do this on a thread where timely responses are expected.

Keep in mind that your thread will sleep for the duration in all cases. If for some reason you want the thread to resume sooner, you're better off using signaling or callbacks. By using either of these instead of Sleep, you will minimize the needless wait time.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
1
void Method()
{
    Statement1();
    Statement2();

    // Start the timer for a single 15 second shot.
    // Keep a reference to it (Mytimer) so that the timer doesn't get collected as garbage
    Mytimer = new System.Threading.Timer((a) =>
        {
            // Invoke the 3rd statement on the GUI thread
            BeginInvoke(new Action(()=>{ Statement3(); }));
        }, 
    null,
    15000, // 15 seconds
    System.Threading.Timeout.Infinite); // No repeat
}
noelicus
  • 14,468
  • 3
  • 92
  • 111
-1

I don't sure 100%, but if you really need your method to return after waiting 15 sec, try following:


Method()
{
   stmt1();
   stmt2();

   int time = DateTime.Now.Millisecond;
   while (15*1000 > DateTime.Now.Millisecond - time)
   {
       Thread.Sleep(10)
       Application.DoEvents();
   }
   stmt3();
}

Pavel Alexeev
  • 6,026
  • 4
  • 43
  • 51