C# 单声道高分辨率定时器(Linux上)
我正在将一个50毫秒(用于串行通信)的windows C#应用程序移植到Linux(使用Mono)。目前,我们正在使用ZylTimer(由ZylSoft提供)在每个时间间隔生成“滴答”事件,但是由于该库包装了对windows多媒体库的pInvoke调用,我们当然不能使用它C# 单声道高分辨率定时器(Linux上),c#,linux,events,mono,C#,Linux,Events,Mono,我正在将一个50毫秒(用于串行通信)的windows C#应用程序移植到Linux(使用Mono)。目前,我们正在使用ZylTimer(由ZylSoft提供)在每个时间间隔生成“滴答”事件,但是由于该库包装了对windows多媒体库的pInvoke调用,我们当然不能使用它 //i.e. timZylComms.Tick += new ZylTimer.TickEventHandler(timZylComms_Tick); timTimeout.Tick +
//i.e.
timZylComms.Tick += new ZylTimer.TickEventHandler(timZylComms_Tick);
timTimeout.Tick += new ZylTimer.TickEventHandler(timTimeout_Tick);
所以,这让我想问,在Mono下是否存在一种替代方案?
最好的方法是用滴答声事件扩展“秒表”类(以高分辨率计数)吗
或者我可以包装一些linux库来复制这个功能吗?
还是有其他方法可以实现这一点
感谢您对此的任何想法
编辑:
这样做会不会有什么问题:
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 ();
}
}
这就是我现在拥有的 它完成了这项工作(通过在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();
}
有没有办法包装POSIX时钟_gettime()来实现这一点?请使用System.Diagnostics.Stopwatch@rytis-i Stopwatch没有tick()方法。最好的方法是用滴答声事件扩展“秒表”类(以高分辨率计数)吗?