gpt4 book ai didi

c# - 事件计时器在 .NET 中延迟,而不是在 Mono 中。这是一个错误吗?

转载 作者:太空狗 更新时间:2023-10-30 01:22:17 25 4
gpt4 key购买 nike

DotNet 替代方案 (MONO- http://www.go-mono.com/mono-downloads/download.html ) 正确处理短定时器条件(低至 ~12 毫秒触发时间)然而,DotNet 似乎比预期和“未命中”花费更长的时间。那么,哪种行为是正确的呢? mono 是否正确跟踪它的事件触发?它是否用不正确的秒表捏造了它的数字?还是 DotNet 有一个“惰性”事件计时器?根据我的测试,很明显,这不是潜在的 Windows 问题。

.NET 200ms+ Interval minimum

Mono 12ms+ Interval minimum

此查询类似于:Timer takes 10 ms more than interval .

但是考虑代码:

在 .NET 中,错过的事件会慢慢增加:

Total Runtime/Interval - Actual Events = Missed Events

代码:

class Program
{
const int Interval = 60; //ms Event fireing

Stopwatch TotalRunTime = new Stopwatch();//Full runtime.
Stopwatch Calctime = new Stopwatch(); //Used to load up the Event to 66 percent

System.Timers.Timer TIMER; //Fireing Event handler.
int TotalCycles = 0; //Number of times the event is fired.
int Calcs_per_cycle = 100; // Number of calcs per Event.

static void Main(string[] args)
{
Program P = new Program();
P.MainLoop();
}

void MainLoop()
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;

TIMER = new Timers.Timer();
TIMER.Interval = Interval;
TIMER.Elapsed += new ElapsedEventHandler(MS_Calc);
TIMER.AutoReset = true;
TIMER.Enabled = true; //Start Event Timer
TotalRunTime.Start(); //Start Total Time Stopwatch;

while (true)
{
Thread.Sleep(Interval * 5);
Console.Clear();
PrintAtPos(2, "Missed Events " + (((TotalRunTime.ElapsedMilliseconds / Interval) - TotalCycles).ToString()));

}

}
public void MS_Calc(object source, System.Timers.ElapsedEventArgs E)// public void MS_Calc(object source, ElapsedEventArgs E)
{
TotalCycles++;
Calctime.Start();
for (int i = 0; i < Calcs_per_cycle; i++)
{
int A = 2;
int B = 2;
int c = A + B;
}
PrintAtPos(1, "Garbge Collections G1: " + GC.CollectionCount(0) + " G2: " + GC.CollectionCount(1) + " G3: " + GC.CollectionCount(2) + " ");
Calctime.Stop();
if (Interval * 0.667 > Calctime.ElapsedMilliseconds) //only fill the even timer 2/3s
//full to make sure we finish before the next event
{
Calcs_per_cycle = (int)(Calcs_per_cycle * 1.035);
}
Calctime.Reset();
PrintAtPos(0, "Calc Time : " + (DateTime.Now - E.SignalTime).Milliseconds + " Calcs/Cycle: " + Calcs_per_cycle);
}

private static void PrintAtPos(int Vertical_Pos, string Entry)
{
Console.SetCursorPosition(0, Vertical_Pos);
Console.Write(Entry);
}
}

最佳答案

问题是 Windows 系统时钟在您使用的时间刻度上不精确,我相信 Microsoft 的 Timer 实现正在使用系统时钟来确定何时触发 Elapsed 事件。我这样假设是因为当您考虑到系统时钟的(不)准确度时,您会得到对观察到的行为的相当准确的描述。

系统时钟仅精确到 15.6 毫秒(原因是为了延长电池生命周期,请参阅 this 问题)。因此,Elapsed 事件并不是准确地每 60 毫秒触发一次,而是每 62.4 毫秒触发一次。这 2.4 毫秒的差异聚合在一起,您就“错过”了事件。我运行了您的程序 33009 毫秒,报告了 22 个错过的事件。我预计会有 33009 * (1/60 - 1/62.4) = 21.2 事件的差异。考虑到我们没有更高准确度的 15.6 毫秒数字,这与您将获得的结果差不多。 (例如,如果耗时为 62.5 毫秒,您将得到 22.0 次预期未命中)。

您的示例肯定表明Timer 的框架实现可以 更准确。不知道为什么Mono的实现更准确,但一般定时器都不是为了精确的毫秒计时。 Stopwatch 类在可用时使用了其他比系统时钟更准确的计时方法。

关于c# - 事件计时器在 .NET 中延迟,而不是在 Mono 中。这是一个错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13965254/

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