Я пишу небольшой счетчик коленей для гоночных автомобилей в качестве небольшого домашнего проекта. Я хочу, чтобы реализовать таймер обратного отсчета, который я сделал со следующим в качестве теста:Более эффективный способ реализации таймера обратного отсчета/часов?
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-секундный обратный отсчет, как я хочу, но я вижу, что я использую много процессора в этом процессе (12% от моего 8-го потока i7 2600k).
Я полагаю, что я могу уменьшить эту нагрузку много, только обновление пользовательского интерфейса каждые 10 миллисекунд, а не каждую миллисекунду, но я понятия не имею, как это сделать, например, кроме использования if(time % 10 == 0)
перед выполнением TimeSpan
и обновление пользовательского интерфейса, но я Подозреваю, что это будет так же неэффективно благодаря циклу while.
Я изобретаю колесо? Я хотел бы, чтобы мой таймер был максимально точным (по крайней мере, для записей времени в игровом автомате для слотов, возможно, пользовательский интерфейс не обязательно должен обновляться так часто).
EDIT: Я пробовал комментировать фактические манипуляции с строкой и обновление пользовательского интерфейса, как это предлагается в комментариях. Теперь, когда я запускаю свой поток, весь мой пользовательский интерфейс зависает, пока поток не выйдет, и я все равно получаю 12% использования ЦП. Я подозреваю, что в то время как цикл ел много процессорного времени.
Обновление: Я пошел с мультимедийным таймером (here), отправленным Kohanz, а также ответом Даниэля. Я больше не использую другой поток, я просто делаю один из этих объектов таймера и обработчик события тика вычисляет время между нажатием кнопки запуска и событием тика. Я даже могу установить период для моих тиков до 1 мс, поэтому я получаю свой крутой обратный отсчет, и, по-видимому, он использует 0% процессор :) Я вполне доволен этим.
вы можете создать еще один поток, отвечающий за обновление пользовательского интерфейса, который входит в сон на N миллисекунд после обновления. – OnoSendai
Вы видели класс Timer http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx, который имеет .Net? – hatchet
Если вы не возражаете, я спрашиваю: кто способен читать 10 миллисекундных изменений на ui? Разве не было бы достаточно обновления каждые 100 или 200 мс? Тогда вы можете просто использовать обычный таймер. – Alex