我正在寻找Mono上的高分辨率刻度计数器,最好是与Win32/.NET上的QueryPerformanceCounter大致相同的分辨率。单声道跨平台高分辨率刻度计?
这是需要在每个我需要支持的平台上作为本地调用(如QueryPerformanceCounter在.NET/Win32上)实现的东西吗? (Linux,OSX)。
我需要约< 1ms分辨率。
我正在寻找Mono上的高分辨率刻度计数器,最好是与Win32/.NET上的QueryPerformanceCounter大致相同的分辨率。单声道跨平台高分辨率刻度计?
这是需要在每个我需要支持的平台上作为本地调用(如QueryPerformanceCounter在.NET/Win32上)实现的东西吗? (Linux,OSX)。
我需要约< 1ms分辨率。
您应该为此使用System.Diagnostics.Stopwatch。
见我的答案在这里: https://stackoverflow.com/a/37882723/5073786
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();
}
这里是我的答案在这里High resolution timer
https://gist.github.com/DraTeots/436019368d32007284f8a12f1ba0f545
它适用于所有平台(所以没有using Mono.Unix.Native;
),是高精度的地方StopWatch.IsHighPrecision == true
其Elapsed
事件是保证非重叠(这可能是知道重要,因为事件处理中的状态变化可能离开对多线程访问未受保护的)
这里是如何使用它:
Console.WriteLine($"IsHighResolution = {HighResolutionTimer.IsHighResolution}");
Console.WriteLine($"Tick time length = {HighResolutionTimer.TickLength} [ms]");
var timer = new HighResolutionTimer(0.5f);
// UseHighPriorityThread = true, sets the execution thread
// to ThreadPriority.Highest. It doesn't provide any precision gain
// in most of the cases and may do things worse for other threads.
// It is suggested to do some studies before leaving it true
timer.UseHighPriorityThread = false;
timer.Elapsed += (s, e) => { /*... e.Delay */ }; // The call back
timer.Start();
timer.Stop(); // by default Stop waits for thread.Join()
// which, if called not from Elapsed subscribers,
// would mean that all Elapsed subscribers
// are finished when the Stop function exits
timer.Stop(joinThread:false) // Use if you don't care and don't want to wait
这里是一个benchmar K(和活的示例):
https://gist.github.com/DraTeots/5f454968ae84122b526651ad2d6ef2a3
还值得一提的是:
我在Ubuntu上单声道具有相同的精度。
虽然与基准,最高和一个非常罕见的偏差,我看到打约为0.5毫秒 (这可能意味着什么,它不是实时系统,但仍然值得一提)
Stopwatch ticks are not TimeSpan ticks.在那Windows 10机器 HighResolutionTimer.TickLength为0.23 [ns]。