В C# таймер

Я пытаюсь сделать обратный отсчет с помощью 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 ответов


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

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

в стандартном 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 вместо местного времени.


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

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

и в конструкторе или load event

_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();
}

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

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

label1.Text = "Done!";

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


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

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

- SeriTools