haiyyu
haiyyu

Reputation: 2242

PerformanceCounter in while loop

I am currently trying to write an application that runs the same code exactly 100 times a second. I have done some testing using the built-in timers of the .NET framework. I've tested the System.Threading.Timer class, the System.Windows.Forms.Timer class and the System.Timers.Timer class. None of them seem to be accurate enough for what I am trying to do. I've found out about PerformanceCounters and am currently trying to implement such in my application. However, I am having a bit of trouble with my program taking up a whole core of my CPU when idling. I only need it to be active 100 times a second. My loop looks like this:

long nextTick, nextMeasure;

QueryPerformanceCounter(out start);
nextTick = start + countsPerTick;
nextMeasure = start + performanceFrequency;

long currentCount;
while (true)
{
    QueryPerformanceCounter(out currentCount);

    if (currentCount >= nextMeasure)
    {
        Debug.Print("Ticks this second: " + tickCount);
        tickCount = 0;
        nextMeasure += performanceFrequency;
    }

    if (currentCount >= nextTick)
    {
        Calculations();
        tickCount++;

        nextTick += countsPerTick;
    }
}

As you can see, most of the time the program will be waiting to run Calculations() again by running through the while loop constantly. Is there a way to stop this from happening? I don't want to slow the computers my program will be run on down. System.Thread.Thread.Sleep unfortunately is also pretty "inaccurate", but I would be okay with using it if there is no other solution.

What I am basically asking is this: Is there a way to make an infinite loop less CPU-intensive? Is there any other way of accurately waiting for a specific amount of time?

Upvotes: 0

Views: 406

Answers (2)

CodesInChaos
CodesInChaos

Reputation: 108810

timeBeginPeriod(1) together with a normal timer or Thread.Sleep should work decently.

Note that this has a global effect. There are claims that it increases power consumption, since it forces the windows timer to run more often, shortening the CPU sleeping periods. This means you should generally avoid it. But if you need highly accurate timing, it's certainly a better choice than a busy-wait.

Upvotes: 1

As I'm sure you're aware, Windows is not a real-time O/S, so there can never be any guarantee that your code will run as often as you want.

Having said that, the most efficient in terms of yielding to other threads is probably to use Thread.Sleep() as the timer. If you want higher accuracy than the default you can issue a timeBeginPeriod with the desired resolution down to a millisecond. The function must be DLLImported from winmm.dll.

Upvotes: 2

Related Questions