gpt4 book ai didi

c# - 单声道高分辨率计时器(在 Linux 上)

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:24:21 24 4
gpt4 key购买 nike

我正在将一个以 50 毫秒(对于串行通信)进行轮询的 Windows C# 应用程序移植到 Linux(使用 Mono)。我们目前正在使用 ZylTimer(由 ZylSoft 提供)在每个时间间隔生成“滴答”事件,但是由于该库包装了对 windows 多媒体库的 pInvoke 调用,我们当然不能使用它。

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

所以,这让我想问是否存在我可以在 Mono 下使用的替代方案?最好的方法是使用 Tick 事件扩展“秒表”类(以高分辨率计算)吗?

或者是否有任何我可以包装的 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 ();
}
}

最佳答案

这就是我现在拥有的。

它完成了工作(在 25 毫秒时生成滴答测试)。

它通过使用 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();
}

关于c# - 单声道高分辨率计时器(在 Linux 上),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37814505/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com