使用Windows Forms编写一个小型OpenGL应用程序时,我发现了一些使用我认为非常不稳定的分析器的东西。
我正在使用System::Windows::Forms::Timer来检测鼠标空闲和其他一些用户输入的组合。刻度功能很有用,但偶尔我想“重置”计时器。你不能直接这样做,但通过这样做可以得到正确的效果:
this->someTimer->Stop();
this->someTimer->Start();
定时器间隔为50毫秒。有时我的“重置”代码每30分钟运行一次。令我惊讶的是,这是一件非常繁重的事情 - 我的程序执行中有30%经常出现在这两行中!并不是经常调用这两行的情况。在某些人为的情况下,这个代码通常被称为OpenGLSwapBuffers()
,但不多。我认为这意味着这两行的成本大约是整个渲染循环的一半!
目前我正在使用一种解决方法,但计时器方法更优雅一些。我很好奇 - 为什么这两条线的计算成本如此之高?我错过了什么?有没有更好的方法来重置计时器?
答案 0 :(得分:3)
调用Start()和Stop()设置一个内部“enabled”标志,每次设置时(在Start的情况下)或unset(在Stop的情况下)执行以下工作:
public virtual void set_Enabled(bool value)
{
lock (this.syncObj)
{
if (this.enabled != value)
{
this.enabled = value;
if (!base.DesignMode)
{
if (value)
{
if (this.timerWindow == null)
{
this.timerWindow = new TimerNativeWindow(this);
}
this.timerRoot = GCHandle.Alloc(this);
this.timerWindow.StartTimer(this.interval);
}
else
{
if (this.timerWindow != null)
{
this.timerWindow.StopTimer();
}
if (this.timerRoot.IsAllocated)
{
this.timerRoot.Free();
}
}
}
}
}
}
正如您所看到的,涉及到的工作,包括句柄分配和管理,除了简单地设置内部标志之外。这可能是您所看到的问题的代价。
作为您的问题的可能解决方案,我想提醒您注意.NET Framework中有三个计时器实现这一事实:
System.Timers.Timer和System.Threading.Timer实现是计时器功能的轻量级实现,您应该调查其中一个较轻的实现是否更高性能并且仍然满足项目的要求。有关这些实现之间功能的差异,请参阅this blog post from Mark Michaelis。