Thread.Sleep() resolution varies from 1 to 15.6ms
Given this console app:
class Program
{
static void Main()
{
int o
I can answer one of my questions: Can I make it consistently accurate? (~1ms resolution)
Yes, it seems that I can, using timeBeginPeriod() and timeEndPeriod().
I've tested this and it works.
Some things I've read suggest that calling timeBeginPeriod(1) for the duration of the application is a bad idea. However, calling it at the start of a short method and then clearing it with timeEndPeriod() at the end of the method should be okay.
Nevertheless I will also investigate using timers.
The answer is not to use Thread.Sleep
and instead use a high resolution timer. You'll need to do your fade in a busy loop, but it sounds like that would be no problem. You simply cannot expect high resolution from Thread.Sleep
and it is notorious for behaving differently on different hardware.
You can use the Stopwatch class on .net which uses high-resolution performance counters if they are supported on the hardware.
You have a program running on your machine that is calling timeBeginPeriod() and timeEndPeriod(). Typically a media related program that uses timeSetEvent() to set a one millisecond timer. It affects the resolution of Sleep() as well.
You could pinvoke these functions yourself to get consistent behavior. Not terribly reasonable for UI effects though. It is rather unfriendly to battery life on a laptop.
Sleeping for 20 msec and actually getting 2/64 seconds is otherwise logical, the cpu simply won't wake up soon enough to notice that 20 msec have passed. You only get multiples of 1/64 seconds. So a reasonable choice for a Timer that implements fading effects is 15 msec, giving you 64 fps animation worst case. Assuming that your effect draws fast enough. You'll be a bit off if timeBeginPeriod was called but not by much. Calculating the animation stage from the clock works too but is a bit overkill in my book.
Your approach is wrong. You will never get sleep to be accurate, and the more busy your machine is, the more wrong your sleep loop will become.
What you should be doing is looking at how much time has passed and adapting accordingly. Although spinning around Sleep is a bad idea, "better" ways of doing it will be significantly more complex. I'll keep my suggested solution simple.
“The Sleep function suspends the execution of the current thread for at least the specified interval.”
-> http://social.msdn.microsoft.com/Forums/en/clr/thread/facc2b57-9a27-4049-bb32-ef093fbf4c29