How can I use CreateTimerQueueTimer to create a high resolution timer in C #?

I used the Windows multimedia dll to create a high resolution timer with

timSetEvent ()

But on the timeSetEvent() page, timeSetEvent() recommended to use:

CreateTimerQueueTimer ()

How can I use CreateTimerQueueTimer () to execute a method every 10 milliseconds in C #?

+7
c # timer
source share
3 answers

Here is a link to the C # shell for CreateTimerQueueTimer :

http://social.msdn.microsoft.com/Forums/en-CA/csharpgeneral/thread/822aed2d-dca0-4a8e-8130-20fab69557d2

(scroll down to the last Hobz message for the sample class)

I just tried it myself and it works great. However, you need to add another call to timeBeginPeriod(1) before starting the timer to set the system to high resolution. timeSetEvent calls timeBeginPeriod internally, so some people mistakenly believe that it creates a timer with a higher resolution.

+9
source share

The callback passed to CreateTimerQueueTimer is expected to be the unmanaged function that will exist for the callback lifetime. A managed delegate can move around in memory, but the basic stub created by marshalling will not do this, so there is no need to bind a delegate . However, there is a need to keep the delegate from garbage collection, because a pointer from unmanaged code is not enough to save it. Thus, you must ensure that either the delegate is supported by a supported managed link (possibly using GCHandle

The PVOID parameter that is passed to the callback function must be fixed in memory, since again the unmanaged function expects it to not move after the function returns. In .Net, this pinning occurs (efficiently) automatically, but only for the life of the called function. Thus, if you use a link to some managed object (say, by getting IntPtr to it), the base object must be docked (again, GCHandle can be used for this in different ways). To make sure this is a problem, try using IntPtr.Zero as a parameter to check if it works.

If this solves the problem, you need to either assign your parameter as raw bytes in the unmanaged heap (and accordingly the marshal), use some type of blittable, which can be safely inserted into some PVOID size (for example, Int32) or use the GCHandle above to support a stable pointer to a managed instance, this will have significant performance implications if done incorrectly.

+3
source share

It is better to use timeSetEvent because its results are more consistent. The average modern equipment, for small intervals, deviations in the length of the intervals is about ten times less than when using CreateTimerQueueTimer. And this assumes that you did not forget to increase the resolution of the timer before calling CreateTimerQueueTimer, otherwise the difference will be even greater. So use timeSetEvent instead.

+2
source share

All Articles