单声道高分辨率定时器(在Linux上) [英] Mono High Resolution timer (on Linux)

查看:241
本文介绍了单声道高分辨率定时器(在Linux上)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我移植了民意调查在50毫秒(用于串行通信)到Linux(使用单声道)一个窗口C#应用程序。目前,我们正在使用的ZylTimer(由ZylSoft)生成在每个时间间隔嘀的事件,但是,因为这个库包的PInvoke调用Windows的多媒体库,我们当然不能用这个。

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



所以,这导致我问,如果不是存在一个替代的,我可以在Mono下使用?
。将最好的办法是用一个Tick事件延长秒表级(其计算在高分辨率)?



还是有任何Linux库,我可以换到重现此功能?
还是有实现这一目标的一些其他的方式?



欣赏任何对此的思考。



编辑:
会不会有任何问题与此打算:

 内部类LinuxHiResTimer {

内部事件的EventHandler蜱;
私人System.Diagnostics.Stopwatch手表;

内部INT间隔{搞定;设置;}
启用私人BOOL;
内部布尔启用{
{返回启用; }
集合{
如果(价值){
watch.Start();
Task.Run(tickGenerator);
=使能值;
}其他{
=使能值;
}
}

}
私人异步任务tickGenerator(){
,而(启用){
如果(watch.ElapsedMilliseconds>间隔){
watch.Reset();
如果(蜱!= NULL)
蜱(这一点,新的EventArgs());
}其他{
浮动fWaitPeriod =(浮点)(0.8 *(间隔 - watch.ElapsedMilliseconds));
如果(fWaitPeriod→20)
等待Task.Delay(TimeSpan.FromMilliseconds(fWaitPeriod));
}
}
watch.Stop();
}

内部LinuxHiResTimer(){

手表=新秒表();
}

〜LinuxHiResTimer(){
watch.Stop();
}
}


解决方案

这就是我现在有。



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



它的工作原理是利用了nanosleep() (通过Mono.Unix.Native包装),我想与其他人的情况下,他们正在寻找实现一些类似的分享。

 使用Mono.Unix.Native; 
命名空间drone.StackOverflow {

内部类LinuxHiResTimer {
内部事件的EventHandler蜱; // Tick事件

私人System.Diagnostics.Stopwatch手表; //高分辨率时间
常量UINT safeDelay = 0; //毫秒(对于稍早唤醒)
私人TIMESPEC pendingNanosleepParams =新TIMESPEC();
私人TIMESPEC threadNanosleepParams =新TIMESPEC();
对象lockObject =新的对象();
内部间隔长{
获得{
双totalNanoseconds;
锁(lockObject){
totalNanoseconds =(1E9 * pendingNanosleepParams.tv_sec)
+ pendingNanosleepParams.tv_nsec;


}
返回(int)的(totalNanoseconds * 1E-6); //以毫秒
}
集合{
返回值锁定(lockObject){
pendingNanosleepParams.tv_sec =价值/ 1000;
pendingNanosleepParams.tv_nsec =(长)((价值1000%)* 1e6个电子); // ns中设定的值
}
}
}
启用私人BOOL;
内部布尔启用{
{返回启用; }
集合{
如果(价值){
watch.Start();
=使能值;
Task.Run(()=> tickGenerator()); //火了新的线程
}
,否则{
锁(lockObject){
=使能值;
}
}
}

}
私人任务tickGenerator(){
布尔bNotPendingStop;
锁(lockObject){
bNotPendingStop =启用;
}
,而(bNotPendingStop){
//检查是否线程已被告知停止

锁(lockObject){
bNotPendingStop =启用;
}
长CURTIME = watch.ElapsedMilliseconds;
如果(CURTIME> =间隔){
watch.Restart();
如果(蜱!= NULL)
蜱(这一点,新的EventArgs());
}其他{
长iTimeLeft =(间隔 - CURTIME); //多长时间拖延
如果(iTimeLeft> = safeDelay){// Task.Delay具有15ms的分辨率//等待Task.Delay(TimeSpan.FromMilliseconds(iTimeLeft - safeDelay));
threadNanosleepParams.tv_nsec =(INT)((iTimeLeft - safeDelay)* 1e6个电子);
threadNanosleepParams.tv_sec = 0;
Syscall.nanosleep(REF threadNanosleepParams,裁判threadNanosleepParams);
}
}

}
watch.Stop();
返回NULL;
}
}



用法:

 私人myMainFunction(){
LinuxHiResTimer timReallyFast =新LinuxHiResTimer();
timReallyFast.Interval = 25; //
timReallyFast.Tick + =新的EventHandler(timReallyFast_Tick);
timReallyFast.Enabled = TRUE;
}
私人无效timReallyFast_Tick(System.Object的发件人,发送System.EventArgs){
//做到这一点很快即
PollSerialPort();
}


I am porting a windows C# application that polls at 50ms (for serial comms) to Linux (using Mono). We are currently using the ZylTimer (by ZylSoft) to generate "tick" events at each interval , however as this library wraps pInvoke calls to the windows multimedia library, we of course cannot use this.

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

So, this leads me to ask if either there exists an alternative I can use under Mono? Would the best approach be to extend the "Stopwatch" class (which counts at a high resolution) with a Tick event?

Or are there any linux libraries I can wrap to reproduce this functionality? Or is there some other way of achieving this?

Appreciate any thoughts on this.

EDIT: Would there be any problems with going with this:

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

解决方案

This is what I have now.

It does the job (tested with generating ticks at 25ms).

It works by using nanosleep() (through the Mono.Unix.Native wrapper), and I would like to share this with others in case they are looking to implement something similar.

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;
    }
}

Usage:

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

这篇关于单声道高分辨率定时器(在Linux上)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆