views:

94

answers:

2

I setup a timer to call an event in my application. The problme is the event execution is being skewed by other windows operations. Ex. openning and window, loading a webpage. I need the event to excute exactly on time, every time.

When i first set up the app, used a sound file, like a metronome to listen to the even firing, in a steady state, its firing right on, but as soon do something in the windows environment, the sound fires slower, then sort of sppeds up a bit to catch up.

So i added a logging method to the event to ctahc the timer ticks. From that data, it appears that the timer is not being affected by the windows app, but my application event calls are being affected. I figured this out by checking the datetime.now in the event, and if i set it to 250 milliseconds, which is 4 clicks per second. You get data something like below.

(sec):(ms)

1:000 1:250 1:500 1:750

2:000 2:250 2:500 2:750

3:000 3:250 3:500 3:750

(lets say i execute some windows event)(time will skew)

4:122 4:388 4:600 4:876

(stop doing what i was doing in windows) (going to shorten the data for simplicit, my list was 30sec long)

5:124 5:268 5:500 5:750

(you would se the time go back the same milliseconds it was at the begining)

6:000 6:250 6:500 6:750

7:000 7:250 7:500 7:750

So i'm thinking the timer continues to fire on the same millisecond every time, but its the event that is being skewed to fire off time by other windows operations. Its not a huge skew, but for what i need to accomplish, its unacceptable.

Is there anyhting i can do in .NET, hoping to use XAML/WPF application, thats will correct the skewing of events?

thx.

+1  A: 

Doing that right could be very, very tricky, if possible at all. Certain audio processing applications really struggle hard to do that. Standard Computer setups are not exactly made for this kind of realtime operation, because you can't control how many threads / processes will run in the background.

However, as a first attempt, you could use a loop instead of an asynchronous trigger. Note that this might grow heavy on the CPU and still does not guarantee precise timing. Pseudo-Code:

forever
{
     // This will bring your precision down to the level of thread 
     // timing precision
     Sleep(0); 

     LastTime = GetPerformanceTimer();
     if(LastTime > NextInterval)
     {
         // Play sound, update last time
     }
}

where GetPerformanceTimer is some kind of QueryPerformanceCounter based method. I wrote a very simple profiler once http://www.emphess.net/2009/03/04/a-very-simple-profiler/, but the code in there is very easy and basically gives you the time in seconds since the timer started with very high precision.

You might also want to give your process higher priority so other processes will not stall your process.

mnemosyn
What about Win32 multimedia timer services? Is there a good example somewhere how to set the application to a higher priority?
First of all, you can specifically adjust the precision of `timeGetTime` using `timeBeginPeriod`. Note that the default precision of the windows multimedia timer is terrible (about 10ms!), whereas QPF is in the microseconds. See this link on MSDN http://msdn.microsoft.com/en-us/library/dd757629(VS.85).aspx. However, I have never used that before. Thinking again, I wouldn't mess with the threads priority.
mnemosyn
Could the problem also be playing a WAV file versus a MIDI sound? Or just the way i am playing the WAV file? Believe i used System.Media.SoundPlayer. Don;t have code in front of me. This was the Multimedia timer i tried, http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx
There is additional lag due to sound drivers, etc. This is also somewhat hardware-dependent I believe. When experimenting with computer-based DJ tools, I had a problem with different delays on different soundcards, so yes, this can be an issue.What you originally posted was related to measurements of the timer callbacks, however - not actually responding to them so this is quite a different issue. Try to do something really simple instead of playing a sound, e.g. change the color of a rectangle or something.
mnemosyn
I showed the time of each click i a label on the windows form. still saw lag, but not as bad. Wondering if the lag is not off as much as the sound was. Wondering if the ear was really picking up on millisecond changes, or was the sound lagging more then the event caller from the timer.
There is typically a low-level delay due to sound hardware and driver of around 30ms+. However, this should always be the same so it wouldn't matter because it's just a constant shift. Sorry but I don't really know any useful answer I guess.
mnemosyn
A: 

I would expect the timer to fire pretty close to exactly on time, as you have observed. However, even than can be affected if the computer is processor bound.

It appears that you want the events to occur on your UI thread exactly on time, and that's going to be a problem. Code that updates the UI has to execute on the UI thread. If anything else is happening on the UI thread when the timer fires, the update operation from the timer has to wait.

I consider it unlikely that you'll be able to get the UI to update exactly on time because there's too much variability in what's going on at any particular moment. This will be especially true on a single processor machine.

If you don't need to update the UI, you can get slightly more consistent response by using a System.Threading.Timer with a callback method reather than using one of the timers that uses events. Still, I would be very surprised if you could get any timer-based method to work reliably in this application.

Jim Mischel