Link: http://www.mindcontrol.org/~hplus/misc/windows-event-loop.html
They typical Windows event loop in a game or tool may look something like:
while( running ) {
if( PeekMessage( ... ) ) {
TranslateMessage( ... );
DispatchMessage( ... );
}
Render();
}
|
Bad Code
There are at least two problems with that:
1) You're calling PeekMessage(), which immediately returns, so the loop will just spin. GetMessage() will wait until there's a message available (and yield the CPU).
2) You're calling Render() once per windows message. This is really bad, as certain windows transactions take many messages. Your look should look something like:
HANDLE h = (HANDLE)CreateEvent( 0, false, false, 0 );
while( running ) {
while( PeekMessage( ... ) ) {
TranslateMessage( ... );
DispatchMessage( ... );
}
timeout = CalculateNextFrameTimeout();
if( timeout <= 0 ) { // time to render?
Render();
timeout = CalculateNextFrameTimeout();
}
// use an alertable wait
MsgWaitForMultipleObjectsEx( 1, &h, timeout, QS_ALLEVENTS,
MWMO_ALERTABE|MWMO_INPUTAVAILABLE );
}
CloseHandle( h );
|
Good Code
This code assumes that Render() does something that makes the next call to CalculateNextFrameTimeout() return greater than 0 for a while :-)
This code will keep the frame rate limited, and give up any CPU not needed. It will efficiently dispatch cascades of Windows events. And, most importantly, it will immediately wake up and dispatch any events generated by the user (such as from mousemove, keydown, etc) because it uses an alterable sleep. Sleep() is not alertable.
本文讨论了Windows游戏或工具中常见的事件循环问题,并提供了一种更优的实现方式。通过使用GetMessage而非PeekMessage,可以避免CPU空转并合理利用资源。此外,还介绍了如何通过调整渲染调用频率及采用可中断等待的方式来提高用户体验。
926

被折叠的 条评论
为什么被折叠?



