【问题标题】:C# Simple Countdown - What am I doing wrong?C# 简单倒计时 - 我做错了什么?
【发布时间】:2009-06-02 22:21:29
【问题描述】:

我想用 C# 制作一个简单的倒计时应用程序来作为示例。

对于第一个基本版本,我使用标签来显示当前剩余时间(以秒为单位),并使用按钮开始倒计时。 Button 的 Click-Event 是这样实现的:

private void ButtonStart_Click(object sender, RoutedEventArgs e)
    {
        _time = 60;
        while (_time > 0)
        {
            _time--;
            this.labelTime.Content = _time + "s";
            System.Threading.Thread.Sleep(1000);
        }
    }

现在,当用户单击按钮时,时间实际上会倒计时(因为应用程序冻结(由于 Sleep()))选择的时间量,但标签的上下文不会刷新。

我做错了什么(在线程方面)还是只是 UI 的问题?


感谢您的回答! 我现在使用 System.Windows.Threading.DispatcherTimer 来做你告诉我的。一切正常,所以这个问题得到了正式的回答;)

对于那些感兴趣的人:这是我的代码(基本部分)

public partial class WindowCountdown : Window
{
    private int _time;
    private DispatcherTimer _countdownTimer;

    public WindowCountdown()
    {
        InitializeComponent();
        _countdownTimer = new DispatcherTimer();
        _countdownTimer.Interval = new TimeSpan(0,0,1);
        _countdownTimer.Tick += new EventHandler(CountdownTimerStep);

    }

    private void ButtonStart_Click(object sender, RoutedEventArgs e)
    {
        _time = 10;
        _countdownTimer.Start();

    }

    private void CountdownTimerStep(object sender, EventArgs e)
    {
        if (_time > 0)
        {
            _time--;
            this.labelTime.Content = _time + "s";
        }
        else
            _countdownTimer.Stop();
    }
}

【问题讨论】:

    标签: c# wpf multithreading


    【解决方案1】:

    是的,事件处理程序不应该阻塞——它们应该立即返回。 您应该通过 Timer、BackgroundWorker 或 Thread 来实现这一点(按此优先顺序)。

    【讨论】:

      【解决方案2】:

      您看到的是长时间运行的消息阻塞 Windows 消息队列/泵的效果 - 您更常将其与白色应用程序屏幕和“无响应”相关联。基本上,如果您的线程正在休眠,它不会响应诸如“画自己”之类的消息。您需要对泵进行更改和屈服控制

      有多种方法可以做到这一点(ripper234 很好地列出了它们)。您经常会看到的糟糕方式是:

      { // your count/sleep loop
      
          // bad code - don't do this:
          Application.DoEvents();
          System.Threading.Thread.Sleep(1000);
      }
      

      我提到这个是为了强调做什么;这会导致“重入”和一般代码管理出现很多问题。更好的方法是简单地使用Timer,或者对于更复杂的代码,使用BackgroundWorker。比如:

      using System;
      using System.Windows.Forms;
      class MyForm : Form {
          [STAThread]
          static void Main() {
              Application.EnableVisualStyles();
              Application.Run(new MyForm());
          }
      
          Timer timer;
          MyForm() {
              timer = new Timer();
              count = 10;
              timer.Interval = 1000;
              timer.Tick += timer_Tick;
              timer.Start();
          }
          protected override void Dispose(bool disposing) {
              if (disposing) {
                  timer.Dispose();
              }
              base.Dispose(disposing);
          }
          int count;
          void timer_Tick(object sender, EventArgs e) {
              Text = "Wait for " + count + " seconds...";
              count--;
              if (count == 0)
              {
                  timer.Stop();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多