【问题标题】:C# countdown timerC#倒数计时器
【发布时间】:2011-12-19 17:06:06
【问题描述】:

我正在尝试使用 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!"; 
  }

也出现了解决这个问题的不同方法。提前致谢

【问题讨论】:

  • 如果你想定期更新标签,你需要像循环这样的东西。
  • @javasocute 我他做到了,我怀疑他的理智。这就是 Winforms,而 .net 有处理这些东西的完美机制。没必要为这么点小事引入javascript。

标签: c# .net winforms datetime countdown


【解决方案1】:

你不应该在这里使用Thread.Sleep。 UI 线程上的Thread.Sleep 会阻塞 UI,而在另一个线程上使用它会由于线程同步而导致额外的复杂性。

如果您有 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();
}

有关其他格式选项,请参阅Standard TimeSpan Format Strings

此代码存在的一个问题是,如果系统时钟发生变化,它将无法正常工作。

当使用DateTime.Now 而不是DateTime.UtcNow 时,在切换夏令时或更改时区时也会中断。由于您想确定某个时间点(而不是显示时间),您应该使用 UTC 而不是本地时间。

【讨论】:

  • 非常感谢! +1 很好的答案,但我有一个问题:Error:Operator '&lt;' cannot be applied to operands of type 'System.TimeSpan' and 'int' 我如何解决它?
  • @TheMask 使用TimeSpan.Zero 而不是0
  • CodeInChaos: 真正有用的家伙。完美运行。非常感谢。 :)
  • +1 表示工作代码。一个简单的问题,你提到不要使用现在,而是使用 UtcNow。我已经检查了这两个选项,并且两种方式都很好。您更喜欢 UtcNow 而不是 Now 的任何具体原因?
  • @Rahul 我的最后一段已经解决了这个问题。如果您的代码在夏令时打开/关闭时正在运行,DateTime.Now 将跳一个小时。还有一个更哲学的原因,我认为DateTime 的设计在处理当地时间时不是很好,所以我尽可能避免使用它们。
【解决方案2】:

我会使用类似这样的计时器。首先是几个实例变量。

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

【讨论】:

    【解决方案3】:

    您也可以使用 Timer,因为它可以处理所有问题,例如 UI 锁定。 您可以使用System.Windows.Forms.Timer-Timer。在 MSDN 库中,您可以找到使用它的示例。

    WinForms-Timer 还处理跨 Timer 线程和 UI 线程的调用。

    - SeriTools

    【讨论】:

      【解决方案4】:

      您的代码设置变量然后进入休眠状态 3 分钟,因此 if 语句在离开休眠状态之前不会执行。要么设置一个新线程来更新 UI,要么做这样的事情......

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

      有了第二个线程,你仍然可以在你的程序工作的时候做一些事情。 “完毕!”完成后会出现。

      【讨论】:

      • 使用计时器,而不是Thread.Sleep()。使用 sleep 是浪费线程。
      • 太棒了,谢谢,我本质上不是 C# 人,只是在构建他的代码。
      • 对线程进行预算是一种很好的做法,但不是必需的。如果正在使用 UI,主要的警告是锁定 UI。
      猜你喜欢
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多