Kev*_*ngs 7 c# wpf multithreading
我想用C#做一个简单的Countdown-Application作为例子.
对于第一个和最基本的版本,我使用Label来显示剩余的当前时间(以秒为单位)和一个Button来开始倒计时.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);
        }
    }
Run Code Online (Sandbox Code Playgroud)
现在,当用户单击按钮时,实际倒计时(因为应用程序冻结(由于Sleep())所选的时间量,但Label的上下文未刷新.
我做的事情一般是错的(当谈到线程时)或者它只是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();
    }
}
Run Code Online (Sandbox Code Playgroud)
    您所看到的是阻止Windows消息队列/泵的长时间运行消息的影响 - 您通常将其与白色应用程序屏幕关联并且"无响应".基本上,如果你的线程处于休眠状态,它就不会响应像"自己画画"这样的消息.您需要对泵进行更改并控制.
有多种方法可以做到这一点(ripper234可以很好地列出它们).你经常看到的坏方法是:
{ // your count/sleep loop
    // bad code - don't do this:
    Application.DoEvents();
    System.Threading.Thread.Sleep(1000);
}
Run Code Online (Sandbox Code Playgroud)
我提到这一点只是为了强调不该做的事; 这导致了很多"重入"和一般代码管理的问题.更好的方法是使用a 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           10219 次  |  
        
|   最近记录:  |