2

在使用 Windows 窗体编写一个小型 OpenGL 应用程序时,我发现了一些使用分析器的东西,我认为这很不可靠。

我正在使用System::Windows::Forms::Timer来检测鼠标空闲和其他一些用户输入的组合。刻度功能很有用,但有时我想“重置”计时器。您不能真正直接执行此操作,但您可以通过执行以下操作获得正确的效果:

this->someTimer->Stop();
this->someTimer->Start();

定时器间隔为 50ms。有时我的“重置”代码每 30 毫秒运行一次。令我惊讶的是,这是一件非常费力的事情——我的程序执行的 30% 通常在这两行中!这不是经常调用这两条线的情况。在某些人为的情况下,此代码的调用频率与OpenGLSwapBuffers()示例一样多,但仅此而已。我将其解释为这两条线的成本大约是整个渲染循环的一半!

目前我正在使用一种解决方法,但计时器方法更优雅一些。我很好奇 - 为什么这两行的计算量如此之大?我错过了什么?有没有更好的方法来重置计时器?

4

1 回答 1

3

调用 Start() 和 Stop() 会设置一个内部“启用”标志,它在每次设置(在 Start 的情况下)或取消设置(在 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
  • System.Windows.Forms.Timer

System.Timers.Timer 和 System.Threading.Timer 实现是定时器功能的轻量级实现,您应该调查其中一种更轻量级的实现是否性能更高并且仍然满足项目的要求。有关实现之间的功能差异,请参阅Mark Michaelis 的这篇博客文章

于 2009-11-03T14:48:30.260 回答