c# - high frequency timing .NET -


i'm looking create high frequency callback thread. need function execute @ regular high frequency (up 100hz) interval. realize windows has normal thread execution slice ~15ms. specify regular interval can faster 15ms.

this i'm trying accomplish. have external device needs messaged @ interval. interval variable depending on situation. expect not ever need more 100hz (10ms) message rate.

i can of course implement spin loop, however, hoping there solution not require wasted resources.

the provided links questions/answers not resolve question. while agree question has been asked several different ways, there has not been solution solved problem.

most of answers provided talk using stopwatch , performing timing task manually entirely cpu intensive. viable solutions using multimedia timers had couple pitfalls haans mentioned. have found solution i'll add below. not know of pitfalls @ time plan testing , research. still interested in comments regarding solution.


winapi call via

bool winapi createtimerqueuetimer(   _out_     phandle phnewtimer,   _in_opt_  handle timerqueue,   _in_      waitortimercallback callback,   _in_opt_  pvoid parameter,   _in_      dword duetime,   _in_      dword period,   _in_      ulong flags ); 

and

bool winapi deletetimerqueuetimer(   _in_opt_  handle timerqueue,   _in_      handle timer,   _in_opt_  handle completionevent ); 

link - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682485%28v=vs.85%29.aspx i'm using pinvoke accomplish this. required when dealing multimedia timers however.

my pinvoke signature interested. pinvoke link

[dllimport("kernel32.dll")] static extern bool createtimerqueuetimer(out intptr phnewtimer,    intptr timerqueue, waitortimerdelegate callback, intptr parameter,    uint duetime, uint period, uint flags);  // callback delegate use. public delegate void waitortimerdelegate (intptr lpparameter, bool timerorwaitfired);  [dllimport("kernel32.dll")] static extern bool deletetimerqueuetimer(intptr timerqueue, intptr timer,    intptr completionevent); 

use createtimerqueuetimer start timer callback. use deletetimerqueuetimer stop timer callback. flexible can create custom queues well. however, easiest implementation if single instance needed use default queue.

i tested solution along side 1 using stopwatch spin loop , results received in regards timing identical. however, cpu load different on machine.

stopwatch spin loop - ~12-15% constant cpu load (about 50% of 1 of cores) createtimerqueuetimer - ~3-4% constant cpu load

i feel code maintenance reduced using createtimerqueuetimer option. doesn't require logic added code flow.

there lot of inaccurate information spread through links , comments. yes, default clock tick interrupt 1/64 seconds = 15.625 msec on machines can changed. reason machines appear operate on rate. windows multi-media api, available winmm.dll lets tinker it.

what don't want using stopwatch. you'll accurate interval measurement out of when use in hot loop check if interval has passed. windows treats such thread unkindly when quantum expires, thread won't re-scheduled run while when other threads compete processor. effect easy miss since don't typically debug code other processes actively running , burning cpu time.

the function want use timesetevent(), provides highly accurate timer can go low 1 millisecond. self-correcting, reducing interval if necessary (and possible) catch when previous callback got delayed due scheduling constraints. beware difficult use, callback made threadpool thread, similar system.threading.timer, sure use safe interlocking , take countermeasures ensure won't trouble re-entrancy.

a different approach timebeginperiod(), alters clock interrupt rate. has many side-effects, 1 thread.sleep() becomes more accurate. tends easier solution since can make synchronous. sleep 1 msec , you'll interrupt rate. code play demonstrates way works:

using system; using system.runtime.interopservices; using system.diagnostics; using system.threading;  class program {     static void main(string[] args) {         timebeginperiod(10);         while (!console.keyavailable) {             var sw = stopwatch.startnew();             (int ix = 0; ix < 100; ++ix) thread.sleep(1);             sw.stop();             console.writeline("{0} msec", sw.elapsedmilliseconds);         }         timeendperiod(10);     }      [dllimport("winmm.dll")]     public static extern uint timebeginperiod(int msec);     [dllimport("winmm.dll")]     public static extern uint timeendperiod(int msec); } 

output on machine:

1001 msec 995 msec 999 msec 999 msec 999 msec 991 msec 999 msec 999 msec 999 msec 999 msec 999 msec 990 msec 999 msec 998 msec ... 

do beware of problem approach, if process on machine has lowered clock interrupt rate below 10 msec not second out of code. that's awkward deal with, can make safe asking 1 msec rate , sleeping 10. don't run on battery operated machine. favor timesetevent().


Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

javascript - jQuery .height() return 0 when visible but non-0 when hidden -