定时器触发 Tick 事件,延迟 15 毫秒
Timer firing Tick event with 15 milliseconds delay
我在使用计时器时遇到了一个奇怪的问题。据我所知,计时器的间隔 属性 表示将触发 timer_Tick 事件的循环之间的延迟。
我之前在 Visual Basic 中编程时遇到过确切签名(15 和 16 毫秒延迟)的问题。我创建的任何计时器都会以 15 或 16 毫秒的延迟触发它们的滴答事件。例如,如果我将计时器的间隔设置为 1(这意味着它的 tick 事件应该在 1 秒内被触发 1000 次),该事件反而会在 1 秒内被触发 62 到 66 次(即 1000/16 到 1000/15 ).
我从 5 年前就一直在开发 VB 应用程序,并且总是遇到这个问题(这也意味着我在使用 AMD 和 Intel 处理器的几个不同系统上都遇到过这个问题),现在我再次使用 C#。
我设法解决了这个问题,方法是根据 TickCount 方法(VB 中的 GetTickCount API 和 Environment.TickCount 在 C# 中)。
*TickCount 是自系统启动以来经过的毫秒数。
为了更好地理解问题,我创建了一个 windows 应用程序来计算自执行以来的秒数(就像计时器一样)。每次触发 Tick 事件时,它都依赖于 TickCount 和普通加法。它还通过从 TickCount 的当前值中减去 TickCount 的最后一个值来计算定时器的延迟(如果定时器在 1 秒内真正被触发 1000 次,那么 TickCounts 的差异每次都是 1,因此这意味着没有延迟,但如果差异大于 1,则每次触发计时器的 tick 事件之间会有一些延迟。
代码如下:
public partial class Form1 : Form
{
int localTime = 0, systemTime = 0, baseSystemTime = 0, lastSystemTime = 0;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
// Calculate time based on TickCount
if (baseSystemTime == 0)
baseSystemTime = Environment.TickCount;
systemTime = Environment.TickCount - baseSystemTime;
label2.Text ="System Time: " + ((systemTime / 1000) / 60).ToString() + ":" + ((systemTime / 1000) % 60).ToString();
// Calculate time based on timer1_Tick
localTime++;
label1.Text = "Application Time: " + ((localTime / 1000) / 60).ToString() + ":" + ((localTime / 1000) % 60).ToString();
// Calculate the delay
if (lastSystemTime > 0)
{
label3.Text = "Delay: " + (Environment.TickCount - lastSystemTime).ToString() + " ms";
}
lastSystemTime = Environment.TickCount;
}
}
我还在此处上传了整个解决方案:http://ramt.in/test/TimerDelay.zip
这是应用程序的屏幕截图(延迟 15 毫秒,应用程序计算了 1 秒,而实际上已经过去了 17 秒!):
解决方案只有 50kb,请随意下载并 运行 看看您是否得到与我相同的结果。如果一样,那就是微软世界的定时器有问题了class!
但更重要的是,如果有人知道可能导致此延迟的原因,请与我分享您的知识。
这是一个系统问题,不是 c# 或 VB。要检查您的系统玩具的准确性,可以使用 Stopwatch
class 和两个属性
- IsHighResolution -
The timer used by the Stopwatch class depends on the system hardware and operating system. IsHighResolution is true if the Stopwatch timer is based on a high-resolution performance counter. Otherwise, IsHighResolution is false, which indicates that the Stopwatch timer is based on the system timer.
- 频率
来自 MSDN 的以下代码显示了它的工作原理
public static void DisplayTimerProperties()
{
// Display the timer frequency and resolution.
if (Stopwatch.IsHighResolution)
{
Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
}
else
{
Console.WriteLine("Operations timed using the DateTime class.");
}
long frequency = Stopwatch.Frequency;
Console.WriteLine(" Timer frequency in ticks per second = {0}",
frequency);
long nanosecPerTick = (1000L*1000L*1000L) / frequency;
Console.WriteLine(" Timer is accurate within {0} nanoseconds",
nanosecPerTick);
}
更新
您的代码也有错误:
// Calculate time based on timer1_Tick
localTime++;
label1.Text = "Application Time: " + ((localTime / 1000) / 60).ToString() + ":" + ((localTime / 1000) % 60).ToString();
这一行已经过去了。它只计算 timer1_Tick
是 运行 的次数。 1 毫秒的间隔对于 windows 表单计时器来说太小了。你可以在这里阅读:Timer takes 10 ms more than interval
如果你需要更精确的计时器你可以看看这篇文章Microsecond and Millisecond C# Timer
这与实时与否无关:windows 默认计时器分辨率为 64 ticks/s 或 15.625 毫秒。但是,可以修改系统计时器分辨率以在更高分辨率下运行,例如1 毫秒。请参阅this 对问题“为什么 .NET 计时器的分辨率限制为 15 毫秒?”的回答,以了解如何修改系统计时器分辨率。
我在使用计时器时遇到了一个奇怪的问题。据我所知,计时器的间隔 属性 表示将触发 timer_Tick 事件的循环之间的延迟。
我之前在 Visual Basic 中编程时遇到过确切签名(15 和 16 毫秒延迟)的问题。我创建的任何计时器都会以 15 或 16 毫秒的延迟触发它们的滴答事件。例如,如果我将计时器的间隔设置为 1(这意味着它的 tick 事件应该在 1 秒内被触发 1000 次),该事件反而会在 1 秒内被触发 62 到 66 次(即 1000/16 到 1000/15 ).
我从 5 年前就一直在开发 VB 应用程序,并且总是遇到这个问题(这也意味着我在使用 AMD 和 Intel 处理器的几个不同系统上都遇到过这个问题),现在我再次使用 C#。
我设法解决了这个问题,方法是根据 TickCount 方法(VB 中的 GetTickCount API 和 Environment.TickCount 在 C# 中)。
*TickCount 是自系统启动以来经过的毫秒数。
为了更好地理解问题,我创建了一个 windows 应用程序来计算自执行以来的秒数(就像计时器一样)。每次触发 Tick 事件时,它都依赖于 TickCount 和普通加法。它还通过从 TickCount 的当前值中减去 TickCount 的最后一个值来计算定时器的延迟(如果定时器在 1 秒内真正被触发 1000 次,那么 TickCounts 的差异每次都是 1,因此这意味着没有延迟,但如果差异大于 1,则每次触发计时器的 tick 事件之间会有一些延迟。
代码如下:
public partial class Form1 : Form
{
int localTime = 0, systemTime = 0, baseSystemTime = 0, lastSystemTime = 0;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
// Calculate time based on TickCount
if (baseSystemTime == 0)
baseSystemTime = Environment.TickCount;
systemTime = Environment.TickCount - baseSystemTime;
label2.Text ="System Time: " + ((systemTime / 1000) / 60).ToString() + ":" + ((systemTime / 1000) % 60).ToString();
// Calculate time based on timer1_Tick
localTime++;
label1.Text = "Application Time: " + ((localTime / 1000) / 60).ToString() + ":" + ((localTime / 1000) % 60).ToString();
// Calculate the delay
if (lastSystemTime > 0)
{
label3.Text = "Delay: " + (Environment.TickCount - lastSystemTime).ToString() + " ms";
}
lastSystemTime = Environment.TickCount;
}
}
我还在此处上传了整个解决方案:http://ramt.in/test/TimerDelay.zip
这是应用程序的屏幕截图(延迟 15 毫秒,应用程序计算了 1 秒,而实际上已经过去了 17 秒!):
解决方案只有 50kb,请随意下载并 运行 看看您是否得到与我相同的结果。如果一样,那就是微软世界的定时器有问题了class!
但更重要的是,如果有人知道可能导致此延迟的原因,请与我分享您的知识。
这是一个系统问题,不是 c# 或 VB。要检查您的系统玩具的准确性,可以使用 Stopwatch
class 和两个属性
- IsHighResolution -
The timer used by the Stopwatch class depends on the system hardware and operating system. IsHighResolution is true if the Stopwatch timer is based on a high-resolution performance counter. Otherwise, IsHighResolution is false, which indicates that the Stopwatch timer is based on the system timer.
- 频率
来自 MSDN 的以下代码显示了它的工作原理
public static void DisplayTimerProperties()
{
// Display the timer frequency and resolution.
if (Stopwatch.IsHighResolution)
{
Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
}
else
{
Console.WriteLine("Operations timed using the DateTime class.");
}
long frequency = Stopwatch.Frequency;
Console.WriteLine(" Timer frequency in ticks per second = {0}",
frequency);
long nanosecPerTick = (1000L*1000L*1000L) / frequency;
Console.WriteLine(" Timer is accurate within {0} nanoseconds",
nanosecPerTick);
}
更新
您的代码也有错误:
// Calculate time based on timer1_Tick
localTime++;
label1.Text = "Application Time: " + ((localTime / 1000) / 60).ToString() + ":" + ((localTime / 1000) % 60).ToString();
这一行已经过去了。它只计算 timer1_Tick
是 运行 的次数。 1 毫秒的间隔对于 windows 表单计时器来说太小了。你可以在这里阅读:Timer takes 10 ms more than interval
如果你需要更精确的计时器你可以看看这篇文章Microsecond and Millisecond C# Timer
这与实时与否无关:windows 默认计时器分辨率为 64 ticks/s 或 15.625 毫秒。但是,可以修改系统计时器分辨率以在更高分辨率下运行,例如1 毫秒。请参阅this 对问题“为什么 .NET 计时器的分辨率限制为 15 毫秒?”的回答,以了解如何修改系统计时器分辨率。