В 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