固定frame rate的windows-event-loop

本文讨论了Windows游戏或工具中常见的事件循环问题,并提供了一种更优的实现方式。通过使用GetMessage而非PeekMessage,可以避免CPU空转并合理利用资源。此外,还介绍了如何通过调整渲染调用频率及采用可中断等待的方式来提高用户体验。

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.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值