我在OpenGL上下文窗口中运行了一些动画,所以我需要不断地重绘它.所以我想出了以下代码:
void InitializeRedrawTimer()
{
var timer = new Timer();
timer.Interval = 1000 / 60;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
glWin.Draw();
}
Run Code Online (Sandbox Code Playgroud)
这只能给我40 FPS.如果我将间隔设置为1毫秒,我可以达到60.那么其他20毫秒去哪了?那只是由于计时器的准确性差或者是什么?如果我想让我的程序尽可能快地运行怎么办?有没有办法连续调用draw func?
你可以尝试实现一个游戏循环.
http://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx
基本循环(稍微修改了原始版本和新SDK中的版本以便于阅读):
public void MainLoop()
{
// Hook the application’s idle event
System.Windows.Forms.Application.Idle += new EventHandler(OnApplicationIdle);
System.Windows.Forms.Application.Run(myForm);
}
private void OnApplicationIdle(object sender, EventArgs e)
{
while (AppStillIdle)
{
// Render a frame during idle time (no messages are waiting)
UpdateEnvironment();
Render3DEnvironment();
}
}
private bool AppStillIdle
{
get
{
NativeMethods.Message msg;
return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
}
}
//And the declarations for those two native methods members:
[StructLayout(LayoutKind.Sequential)]
public struct Message
{
public IntPtr hWnd;
public WindowMessage msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point p;
}
[System.Security.SuppressUnmanagedCodeSecurity] // We won’t use this maliciously
[DllImport(“User32.dll”, CharSet=CharSet.Auto)]
public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
Run Code Online (Sandbox Code Playgroud)
简单,优雅,有效.没有额外的分配,没有额外的集合,它只是工作..当队列中没有消息时,Idle事件触发,然后处理程序继续循环,直到出现消息,在这种情况下它停止..一旦所有消息都是处理完毕后,将再次触发idle事件,并重新开始该过程.
此链接描述使用应用程序的空闲事件的链接.它可能是有用的.您可以简单地执行一点时间测试或睡眠以将其减慢到所需的fps.尝试使用System.Diagnostics.StopWatch类获得最准确的计时器.
希望这会有帮助.