单声道高分辨率定时器(在Linux上) [英] Mono High Resolution timer (on 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屋!