2016-06-14 2 views
1

私は50ms(シリアル通信用)をLinux(Monoを使用)にポーリングするWindows C#アプリケーションを移植しています。私たちは現在、ZylSimer(by ZylSoft)を使って各間隔で "tick"イベントを生成していますが、このライブラリはpInvoke呼び出しをWindowsマルチメディアライブラリにラップするので、もちろんこれを使うことはできません。Mono高解像度タイマー(Linux版)

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

これは、私がモノの下で使用できる代替品が存在するかどうかを尋ねます。 ティックイベントで「ストップウォッチ」クラス(高解像度でカウントされるクラス)を拡張するのが最善の方法でしょうか?

また、この機能を再現するためにラップすることのできるライブラリがありますか? これを達成する他の方法がありますか?

これに感謝しています。

EDIT: はこれで行くと何か問題があるでしょう:

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(); 
    } 
} 
+0

これを達成するために、おそらくPOSIXのにclock_gettimeをラップする方法は、()がありますか? – drone

+0

Use System.Diagnostics.Stopwatch http://stackoverflow.com/questions/7736013/cross-platform-high-resolution-tick-counter-on-mono –

+0

@ rytis-i Stopwatchにはtick()メソッドがありません。最良のアプローチは、Tickイベントで "Stopwatch"クラス(高解像度でカウントされる)を拡張することでしょうか? – drone

答えて

0

これは私が今持っているものです。

それは仕事をします(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 i.e. 
PollSerialPort(); 
} 
関連する問題