I've got some animations running in an OpenGL context window, so I need to constantly redraw it. So I came up with the following code:
private void InitializeRedrawTimer()
{
var timer = new Timer();
timer.Interval = 1000 / 60;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
glWin.Draw();
}
That only gives me 40 FPS though. If I set the interval to 1 ms however, I can achieve 60. So where did the other 20 ms go? Is that just due to poor accuracy of the timer or what? What if I wanted to let my program run as fast as possible, is there a way to continuously call the draw func?
The Windows Forms Timer is ultimately limited in resolution to the standard system clock resolution of your computer. This varies from computer to computer, but is generally between 1 ms and 20 ms.
In WinForms, whenever you request a timer interval in code, Windows will only guarantees that your timer will be called no more often then the number of milliseconds specified. It makes no guarantee that your Timer will be called at exactly the milliseconds you specify.
This is because Windows is a time-sharing OS, not real-time. Other processes and threads will be scheduled to run concurrently and so your thread will be forced to wait regularly for usage of the processor. Therefore you shouldn't write WinForms timer code that relies on exact intervals or delays of milliseconds.
In your situation, setting the interval to 1 ms is really just telling Windows to trigger this timer as often as it can. As you have seen this is definitely much less often than 1 ms (60fps = about 17 ms).
If you need a more accurate and higher resolution timer, the Windows API does provide high resolution/performance timers, if your hardware supports it, see How to use the high resolution timer. A drawback of this is that your application CPU usage will be increased to support the higher performance.
Overall I think you're better off implementing a hardware/system independent game loop. That way the perceived animation of your scene appears constant regardless of the actual frame-rate achieved. For more information these articles give a good background.
Depending on what you are doing, have a look at WPF and it's animation support, it may be a better solution that writing your own amimations in WinForms.
Also consider using DirectX as it now has a .NET wrapper and is very fast, however it is harder to use the WPF or WinForms.
To continuously call your draw function:
However your users may not like you killing their computer!
Application.Idle is also another good option, however I like the fact windows will slow down the rate it send WmPaint messages when needed.
You could try implementing a game loop.
http://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx
This link describes one that uses the application's Idle event. It may be of use. You can simply perform a little time test or sleep to slow it down to your required fps. Try using the System.Diagnostics.StopWatch class for the most accurate timer.
I hope this helps a little.
I have noticed in the given sample code in the line:
It uses the operation of integer division, so the result will be rounded to integer and won't be precisely 16.6666ms, but 17ms. Hence the timer make larger ticks than the screen refresh.