小さなホーム プロジェクトとして、スロット カー レース用の小さなラップ カウンターを書いています。カウントダウンタイマーを実装したいと思います。これは、テストとして次のことを行いました。
private Thread countdownThread;
private delegate void UpdateTimer(string update);
UpdateTimer ut;
public LapCounterForm()
{
InitializeComponent();
//...
ut += updateTimer;
countdownThread = new Thread(new ThreadStart(startCountdown));
}
private void startCountdown()
{
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
System.Diagnostics.Stopwatch stopwatch = new Stopwatch();
long time = 0;
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds <= 5000)
{
time = 5000 - stopwatch.ElapsedMilliseconds;
TimeSpan ts = TimeSpan.FromMilliseconds(time);
ut(ts.Minutes.ToString().PadLeft(2, '0') + ":" + ts.Seconds.ToString().PadLeft(2, '0') + ":" + ts.Milliseconds.ToString().PadLeft(3, '0'));
}
}
private void updateTimer(string text)
{
if (this.InvokeRequired)
{
this.Invoke(new Action<String>(ut), new object[] { text });
}
else
{
lblCountdownClock.Text = text;
}
}
スレッドを開始すると、機能します。希望どおりに 5 秒のカウントダウンが表示されますが、プロセスで大量の CPU を使用していることがわかります (8 スレッド i7 2600k の 12%)。
ミリ秒ごとではなく、10ミリ秒ごとにUIを更新するだけで、この負荷を大幅に削減できると思いますが、UIを作成して更新するif(time % 10 == 0)
前に使用する以外に、その方法がわかりませんが、それは同じようになると思いますTimeSpan
while ループのおかげで効率が悪い。
車輪の再発明ですか?タイマーをできるだけ正確にしたいです (少なくともスロットカーのラップタイムの記録については、おそらく UI をそれほど頻繁に更新する必要はありません)。
編集: コメントで提案されているように、実際の文字列操作と UI の更新をコメントアウトしてみました。スレッドを開始すると、スレッドが終了するまで UI 全体がハングし、それでも 12% の CPU 使用率が得られます。while ループが多くの CPU 時間を消費していると思われます。
更新: Kohanz によって投稿されたマルチメディア タイマー ( here ) と Daniel の回答を使用しました。もう別のスレッドはまったく使用しません。タイマー オブジェクトの 1 つを作成し、開始ボタンをクリックしてから tick イベントまでの時間を計算する tick イベント ハンドラーを用意するだけです。ティックの期間を 1 ミリ秒に設定することもできるので、見栄えの良いカウントダウンが表示されます。明らかに 0% の CPU を使用しています :) これには非常に満足しています。