一定周期のループを安定させる方法(C#用メモ)
一定周期の処理を行いたいとき、タイマーを使えば良いのですが、より精度の高い周期で処理を行いたい場合は、次のような方法が考えられます。
これはゲームなどで、1フレーム(1回の画面の更新)の長さを1/60秒に保つために、良く用いられる方法です。
// 次に処理するフレームの時刻(初回は即処理するので初期値は現在時刻をセット) double nextFrame = (double)System.Environment.TickCount; // フレームを処理する周期(1/60秒) float period = 1000f / 60f; // メインループ while ( true ) { // 現在の時刻を取得 double tickCount = (double)System.Environment.TickCount; // 次に処理するフレームの時刻まで間がある場合は、処理をスキップする if (tickCount < nextFrame) { // 1ms以上の間があるか? if (nextFrame - tickCount > 1) { // Sleepする System.Threading.Thread.Sleep( (int)(nextFrame - tickCount) ); } // Windowsメッセージを処理させる Application.DoEvents(); // 残りの処理をスキップする continue; } // // ここで描画以外の計算処理を行う。 // // この時点で現在の時刻が次のフレームの時刻より後ならば、 // このフレームを描画している暇はないので、描画しないでスキップする if ((double)System.Environment.TickCount >= nextFrame + period) { nextFrame += period; continue; } // // ここで描画処理を行う。 // // 次のフレームの時刻を計算する nextFrame += period; }