なにが起こったか
DirectXを活用してゲーム作ってたらウィンドウ閉じるのがとても遅くなってしまいました。
問題個所
SetCursorPos(center.x, center.y);
SetCursorPos()で画面の中央にカーソルを置く命令をしてるだけ、問題なし!
と思っていたらこれが全然ひどかった。
アプリケーション終了時の挙動
Windowsアプリケーションは実行時にユーザーからの入力を受け取るあるいは特定の条件を満たしたときにメッセージを生成します。
このメッセージはメッセージキューに溜まって逐次PeekMessage関数から受け取ることができます。
問題はこのメッセージキュー!
終了時にメッセージキューにメッセージが残ってると自動的に後処理をしてくれます。
したがってこのメッセージキューが残っていれば残っているほど後処理にかかる時間は増えていくということです。
さて、先ほどのコードを見ると
SetCursorPos(center.x, center.y);
実は単に動かすだけではなくカーソルの位置が前から変わっている状態になりWM_MOUSEMOVEメッセージが生成されメッセージキューに入っていたということです。
じゃあもしこれがずっと中央に固定したいからって毎フレーム呼んでいたら...
逐次処理を行う単純な処理だと処理が追い付かずどんどんメッセージキューが溜まって終了したいときには後処理しないといけないメッセージの数が超超膨大になっている!!
結果、アプリケーションを閉じる速度が遅くなった
対処法
SetCursorPos(center.x, center.y);
MSG msg;
while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
マウスを動かしたときのメッセージを使わないならこの方法が一番楽です。
メッセージを使う場合は最初の一回だけメッセージへの対応処理を行いそれ以外のメッセージは無視して破棄する方法かそもそもキューから溢れるほどSetCursorPos()を使わないという方法の二択と考えています。
おわり
メッセージの生成速度と消費速度の差には気を付けましょう。