2016-06-14 4 views
1

저는 직렬 통신을 위해 50ms에서 Mono를 사용하여 Linux로 폴링하는 Windows C# 응용 프로그램을 포팅합니다. 우리는 현재 ZylTimer (by ZylSoft)를 사용하여 각 간격마다 "tick"이벤트를 생성하지만이 라이브러리는 pInvoke 호출을 Windows 멀티미디어 라이브러리에 랩핑하므로 물론 사용할 수 없습니다.Mono 고해상도 타이머 (Linux)

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

따라서, 모노에서 사용할 수있는 대안이 있는지 묻습니다. 틱 이벤트로 "스톱워치"클래스 (고해상도로 계산)를 확장하는 것이 가장 좋은 방법일까요?

또는이 기능을 재현하기 위해 포장 할 수있는 라이브러리가 있습니까? 또는이를 달성하는 다른 방법이 있습니까?

감사합니다.

편집 : 이 함께가는 어떤 문제가 있을까 :

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://stackwatch.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(); 
} 
관련 문제