I have a windows service that can host one or more background threads. Each background thread starts a polling loop to check for work. I’ve been using the following pattern to implement the loop:
new Thread(DoWork).Start();
private void DoWork()
{
while(keepRunning)
{
Console.WriteLine(DateTime.Now);
Thread.Sleep(1000);
}
}
I’m trying to find an alternative that will consume less CPU. I’ve been able to achieve a polling loop using a Timer with a recursive method:
var timer = new Timer(WakeUp, null, Timeout.Infinite, 1000)
timer.Change(0, 1000);
private void WakeUp(object state)
{
lock (locker)
Monitor.Pulse(locker);
}
private void DoWork()
{
lock (locker)
{
if (!keepRunning) return;
Console.WriteLine(DateTime.Now);
Monitor.Wait(locker);
DoWork();
}
}
Are there any advantages to using one pattern over the other? Is there a better pattern for setting up a polling loop in a background thread?
Do you have any evidence that it’s actually consuming a significant amount of CPU at the moment? Unless you’re got a lot of threads which are waking up at similar times and contending, I’d expect
Thread.Sleepto be reasonably efficient.Your recursive
DoWorkmethod is far worse – unless it’s tail-call optimized, you’ll eventually blow up with a stack overflow. Why aren’t you at least looping? Why don’t you just do the actual work in the timer thread to start with?If you really want one thread per task, doing some work once per second, then your first code is okay (although you’ll want to make sure you “see” any new values of
keepRunningif it’s just a field – consider usingInterlocked). Ideally though, you shouldn’t have those threads at all – just have appropriate timers to schedule the work once per second, and let the thread pool handle it.