0

In the .NET framework, is there a better way to pause an application instead of using System.Threading.Thread.Sleep(1000)?

This doesn't only freeze the application events. How do you pause an application without causing it to freeze or getting high CPU usage?

Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
user2625447
  • 9
  • 2
  • 6
  • 3
    What is it that you want to pause? Maybe trying disable controls? – Jeroen van Langen Aug 09 '13 at 11:46
  • 3
    We need to know what you want to achieve in order to give an appropriate answer – Matt Wilko Aug 09 '13 at 12:14
  • Are you using a UI framework like WinForms or WPF? Please add a tag to specify. – lesderid Aug 09 '13 at 12:19
  • If this is a WinForm application (inferred from the reference to the OP 'freezes the application events') the you may see a suggestion to loop and call `Application.DoEvents()` but *don't*. See this question/answer: http://stackoverflow.com/questions/5181777/use-of-application-doevents – Plymouth223 Aug 09 '13 at 11:51

2 Answers2

4

It's hard to answer your question because it's not clear what do you mean under "pause".

What pausing is not

If this is a WinForms application for example, you should have a UI window. This window has many objects stored deep in Windows kernel. (This is why actually it is difficult to make Windows a console-only OS, Microsoft only done this for new 2012 server editions). There is a global message loop that dispatches messages to all windows. This is how you actually see everything on your desktop. Surely you don't want to pause that message loop, which effectively halts Windows and results in undefined behavior/BSOD/system hanging state...

What it is

You probably thinking about pausing some user-level code that your application executes. In this case you can use some asynchronicity here.

Let's assume you do heavy prime number calculations and at some moment want to pause/resume that.

Important! You should do such work on a separate thread, keeping UI thread available for handling display notifications from Windows kernel.

From time to time, user can click on a UI element, which works in the UI thread, and then you can dispatch a pause/resume action to the worker thread.

Arsenal

You could use ManualResetEvent or AutoResetEvent. These classes are specifically designed to pass notifications between threads and as a consequence remove thread (which doesn't need to do any work) from Windows Task Scheduler.

You can think of the reset events as lights switches. When you want some work to be done, you switch it ON. If you want to pause, you switch it OFF. When the *ResetEvent is in the "OFF" state, it doesn't consume any CPU and it doesn't perform any work.

Community
  • 1
  • 1
oleksii
  • 35,458
  • 16
  • 93
  • 163
  • 1
    The two reset event classes don't' really help too much in this case. They still involve the code performing a blocking wait, much like `Thread.Sleep`, and have all of the same drawbacks in this context. – Servy Aug 09 '13 at 14:23
  • 1
    Why would it? My understanding is that when a user does `resetEvent.WaitOne()` than internally it uses mutex. And mutex in turn does not participate in the message handling loop and does not consume any resources, contrary to `Thread.Sleep`. – oleksii Aug 09 '13 at 14:27
  • The result of either operation is the thread pausing execution, and thus not consuming resources. The result of either operation is *also* that, if called from the UI thread, the UI thread will not be able to continue processing messages in the message loop and will result in the application not responding, as opposed to using asynchrony, in which (from the point of the message loop) the message simply finished normally, and zero or more new messages will be added to the loop when execution ought to resume. – Servy Aug 09 '13 at 14:29
  • Yes, but I mentioned that such operations must be performed in another thread. *"In any case, you should do such work on a separate thread, keeping UI thread available for handling display notifications from Windows kernel."*. `Thread.Sleep` consumes some resources when it wakes up, which is a polling-based model. `reset event` is more like a push model, isn't it? – oleksii Aug 09 '13 at 14:32
  • 1
    No. `Thread.Sleep` isn't doing a busy wait. The OS is quite capable of efficiently notifying the thread that it should wake up after a fixed period of time. The operations are equally efficient. My point here is that using either of those events isn't what solves the problem. If you use a worker thread that can be a solution, but if you do that `Thread.Sleep` is just fine if the requirement is to just wait a fixed amount of time. There's no requirement for either of the other classes you mentioned, that's all I was saying. – Servy Aug 09 '13 at 14:35
2

In an async method:

await Task.Delay(1000);
//or 
Task tsk = Task.Delay(1000);
//do work that doesn't depend on the wait
await tsk;
It'sNotALie.
  • 22,289
  • 12
  • 68
  • 103