Таймер обратного отсчета C # - PullRequest
11 голосов
/ 01 ноября 2011

Я пытаюсь сделать обратный отсчет с помощью C # и показать время в формате:

hour:minutes:seconds

Я пробовал это:

 var minutes = 3; //countdown time
  var start = DateTime.Now;
  var end = DateTime.Now.AddMinutes(minutes);
  Thread.Sleep(1800);
  if (??) // I tried DateTime.Now > end not works
  {
       //... show time
      label1.Text = "..."; 
  } 
  else 
  {
     //done 
      label1.Text = "Done!"; 
  }

Различные способы решения этой проблемытакже появился.Заранее спасибо

Ответы [ 4 ]

29 голосов
/ 01 ноября 2011

Вы не должны использовать Thread.Sleep здесь. Thread.Sleep в потоке пользовательского интерфейса блокирует пользовательский интерфейс, а использование его в другом потоке приводит к дополнительной сложности из-за синхронизации потока.

Если у вас есть C # 5 или асинхронный CTP, вы, вероятно, можете написать код, очень похожий на тот, что вы делали, поскольку тогда вы получите эквивалент на основе продолжения Thread.Sleep, который не блокирует пользовательский интерфейс.

В стандартном C # 4 я бы использовал System.Windows.Forms.Timer.

Чтобы начать обратный отсчет:

var minutes = 3; //countdown time
var start = DateTime.UtcNow; // Use UtcNow instead of Now
endTime = start.AddMinutes(minutes); //endTime is a member, not a local variable
timer1.Enabled = true;

В обработчике таймера вы пишете:

TimeSpan remainingTime=endTime-DateTime.UtcNow;
if(remainingTime<TimeSpan.Zero)
{
   label1.Text = "Done!";
   timer1.Enabled=false; 
}
else
{
  label1.Text = remainingTime.ToString();
}

Другие параметры форматирования см. Стандартные строки формата TimeSpan .

Одна проблема, которая остается с этим кодом, состоит в том, что он не будет работать правильно, если системные часы изменятся.

При использовании DateTime.Now вместо DateTime.UtcNow оно также прерывается при переключении с / на летнее время или при смене часового пояса. Поскольку вы хотите определить определенный момент времени (а не время отображения), вы должны использовать UTC вместо местного времени.

6 голосов
/ 01 ноября 2011

Я бы использовал таймер примерно так. Сначала пара переменных экземпляра.

private int _countDown = 30; // Seconds
private Timer _timer;

и в конструкторе или событии загрузки

_timer = new Timer();
_timer.Tick += new EventHandler(timer_Tick);
_timer.Interval = 1000;
_timer.Start();

и, наконец, обработчик события

void timer_Tick(object sender, EventArgs e)
{
    _countDown--;
    if (_countDown < 1)
    {
        _countDown = 30;
    }
    lblCountDown.Text = _countDown.ToString();
}
0 голосов
/ 01 ноября 2011

Вы также можете использовать Таймер , так как это решит все проблемы, такие как UI-блокировка.Вы можете использовать System.Windows.Forms.Timer -Timer.В библиотеке MSDN вы можете найти примеры ее использования.

WinForms-Timer обрабатывает также вызов через поток Timer и поток UI.

- SeriTools

0 голосов
/ 01 ноября 2011

Ваш код устанавливает переменные, затем переходит в спящий режим на 3 минуты, поэтому оператор if не выполняется, пока не выйдет из состояния сна. Либо создайте новый поток для обновления пользовательского интерфейса, либо выполните что-то вроде этого ...

while (DateTime.now < end) {
  label1.Text = "...";
  Thread.Sleep(#); //Pick a second, or 5 or whatever
}

label1.Text = "Done!";

Со вторым потоком вы все еще можете делать что-то в своей программе, пока она работает. "Готово!" появится после его окончания.

...