C#简单倒计时 - 我做错了什么?

7

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

对于第一个和基本版本,我使用一个标签来显示剩余时间(以秒为单位),并使用一个按钮来启动倒计时。按钮的点击事件实现如下:

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();
    }
}
2个回答

10

是的,事件处理程序不应该阻塞 - 它们应该立即返回。

您可以通过定时器、BackgroundWorker 或线程实现此功能(按此顺序优先)。


9
您正在看到的是长时间运行的消息阻塞了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();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接