3

I have a situation where I need a constant loop running in a service, each time checking certain conditions, and then taking action as appropriate. From a design perspective, using a while (true) loop fits perfectly:

while (true)
{
    Process();
}

The Process() method checks the state of an in-memory (fast) data store. If it finds there is work to do based on the state, it Processes it using Task.Run() (so control returns to the loop immediately).

I have seen some references that this will eat up unnecessary CPU cycles, and that I should use a Timer, or add Thread.Sleep to the loop. I have also seen posts stating that there is nothing wrong with using while (true).

On my dev machine, it does not seem to have a negative impact, although the CPU usage does go up. It may be that the CPU usage gets spread across multiple cores, where the deployment environment may only have a single core.

Does a while (true) loop have a negative performance impact on the CPU, and if so, what is the correct way to mitigate the impact?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Phil Sandler
  • 27,544
  • 21
  • 86
  • 147
  • `while(true) { Task.Run(..) } `will definitely peg the CPU. Please look at the Producer Consumer pattern and PubSub pattern on how to do this correctly. – Aron Jun 27 '19 at 07:23

2 Answers2

5

The answer is of course it depends on what you are doing.

A while(true) loop doesn't intrinsically cause bad performance on it's own. The performance danger occurs in the method body, in this case Process().

If the method is intended to run forever and never take a break than this construct is fine. However, if Process is supposed to respond to events or 'listen' for something to occur, placing it in a while(true) loop can cause your processor to unnecessarily poll.

For example,

while (true)
{
   //At the start of every minute
   if (DateTime.Now.Seconds == 0)
       //Do Something
}

This would be very bad. You're having your CPU constantly check a condition that's only true once a minute and preventing the CPU from doing useful work the remainder of the time.

In a situation like this, you'd be better of using some of the functionality available to you in the Threading namespace to release the CPU.

Chris Mantle
  • 6,595
  • 3
  • 34
  • 48
Philip Pittle
  • 11,821
  • 8
  • 59
  • 123
4

In a cooperative multitasking system, this could indeed peg the CPU (or at least, one core).

However, most modern OSes employ preemptive multitasking, which basically means the OS controls how much time your process gets. So although your loop will use 100% of the thread's (or possibly process's) time, and deprive others of some CPU time, the OS will ensure that other processes/threads that are ready to run get time to do so. So at worst, you'll slow things down a bit.

The one thing you want to be especially mindful of, is that such a loop will tie up the thread running it, making that thread unavailable for other stuff. So you don't want to do it on the UI thread, for example. (There's Application.DoEvents(), but you have to call it every so often on your own, and its use is a sign that you're doing something that really belongs in its own thread.)

cHao
  • 84,970
  • 20
  • 145
  • 172
  • They won't be starved out completely, but they'll get less CPU time than they otherwise would while this process is wasting that time doing nothing productive. – Servy Aug 18 '14 at 17:26
  • @Servy: Good point (edited). It'll tie up some time that could otherwise be used for other processes. But the process can only waste the time the OS lets it have, so it can't monopolize the CPU unless someone's screwing around with priorities and/or the OS is badly designed. – cHao Aug 18 '14 at 17:32
  • Correct, it won't completely crash the entire machine, it'll just make the entire machine slower. The OP isn't asking if doing this will completely break his entire machine, he's asking if there are negative consequences. There are negative consequences besides, "you computer can't do anything anymore [insert evil laugh here]". – Servy Aug 18 '14 at 17:34