单声道高分辨率定时器(在Linux上)

我将移植到Linux(使用Mono)的50ms(对于串行通信)轮询的Windows C#应用程序。 我们目前正在使用ZylTimer(通过ZylSoft)在每个间隔产生“tick”事件,但是当这个库将pInvoke调用包装到windows多媒体库时,我们当然不能使用它。

//ie timZylComms.Tick += new ZylTimer.TickEventHandler(timZylComms_Tick); timTimeout.Tick += new ZylTimer.TickEventHandler(timTimeout_Tick); 

所以,这导致我问,如果有任何我可以在单声道下使用的替代品? 最好的方法是用Tick事件扩展“秒表”类(以高分辨率计数)吗?

还是有任何Linux库我可以包装重现此function? 或者还有其他的方式来实现这一点?

欣赏任何想法。

编辑:这会有任何问题:

 internal class LinuxHiResTimer{ internal event EventHandler Tick; private System.Diagnostics.Stopwatch watch; internal int Interval{ get; set;} private bool enabled; internal bool Enabled { get{ return enabled; } set { if (value) { watch.Start (); Task.Run (tickGenerator); enabled = value; } else { enabled = value; } } } private async Task tickGenerator(){ while (enabled){ if (watch.ElapsedMilliseconds > Interval) { watch.Reset (); if (Tick != null) Tick (this, new EventArgs ()); } else { float fWaitPeriod = (float)(0.8 * (Interval - watch.ElapsedMilliseconds)); if (fWaitPeriod>20) await Task.Delay(TimeSpan.FromMilliseconds(fWaitPeriod)); } } watch.Stop (); } internal LinuxHiResTimer(){ watch = new Stopwatch (); } ~LinuxHiResTimer(){ watch.Stop (); } } 

Solutions Collecting From Web of "单声道高分辨率定时器(在Linux上)"

这是我现在所拥有的。

它做的工作(在25ms产生蜱测试)。

它通过使用nanosleep()(通过Mono.Unix.Native包装器)工作,我想与其他人分享,以防他们正在寻求实现类似的东西。

 using Mono.Unix.Native; namespace drone.StackOverflow{ internal class LinuxHiResTimer { internal event EventHandler Tick; // Tick event private System.Diagnostics.Stopwatch watch; // High resolution time const uint safeDelay = 0; // millisecond (for slightly early wakeup) private Timespec pendingNanosleepParams = new Timespec(); private Timespec threadNanosleepParams = new Timespec(); object lockObject = new object(); internal long Interval { get{ double totalNanoseconds; lock (lockObject) { totalNanoseconds= (1e9 * pendingNanosleepParams.tv_sec) + pendingNanosleepParams.tv_nsec; } return (int)(totalNanoseconds * 1e-6);//return value in ms } set{ lock (lockObject) { pendingNanosleepParams.tv_sec = value / 1000; pendingNanosleepParams.tv_nsec = (long)((value % 1000) * 1e6);//set value in ns } } } private bool enabled; internal bool Enabled { get { return enabled; } set { if (value) { watch.Start(); enabled = value; Task.Run(()=>tickGenerator()); // fire up new thread } else { lock (lockObject) { enabled = value; } } } } private Task tickGenerator() { bool bNotPendingStop; lock (lockObject) { bNotPendingStop = enabled; } while (bNotPendingStop) { // Check if thread has been told to halt lock (lockObject) { bNotPendingStop = enabled; } long curTime = watch.ElapsedMilliseconds; if (curTime >= Interval) { watch.Restart (); if (Tick != null) Tick (this, new EventArgs ()); } else { long iTimeLeft = (Interval - curTime); // How long to delay for if (iTimeLeft >= safeDelay) { // Task.Delay has resolution 15ms//await Task.Delay(TimeSpan.FromMilliseconds(iTimeLeft - safeDelay)); threadNanosleepParams.tv_nsec = (int)((iTimeLeft - safeDelay) * 1e6); threadNanosleepParams.tv_sec = 0; Syscall.nanosleep (ref threadNanosleepParams, ref threadNanosleepParams); } } } watch.Stop(); return null; } } 

用法:

  private myMainFunction(){ LinuxHiResTimer timReallyFast = new LinuxHiResTimer(); timReallyFast.Interval=25; // timReallyFast.Tick += new EventHandler(timReallyFast_Tick); timReallyFast.Enabled = true; } private void timReallyFast_Tick(System.Object sender, System.EventArgs e) { // Do this quickly ie PollSerialPort(); }