使用Thread.Sleep()时Wpf标签未更新
我有一个标签我想在每秒后更新的内容,3秒后我只看到最后一个字符串“第3步……”我做错了什么,如果出于某种原因还有另一种方法来实现这一点我不能使用Thread.Sleep():
视图:
查看型号:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Threading; namespace WpfApplication1.Scroller { public class Message { public Message(string _text) { text = _text; } private string text; public string Text { get { return text; } set {text = value;} } } public class ScrollerViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public DelegateCommand AddNew { get; protected set; } ObservableCollection _messages = new ObservableCollection(); public ObservableCollection Messages { get { return _messages; } set { _messages = value; OnPropertyChanged("Messages"); } } public ScrollerViewModel() { AddNew = new DelegateCommand(Add); } private void Add(object parameter) { UpdateProgress("Step 1..."); UpdateProgress("Step 2..."); UpdateProgress("Step 3..."); } private void UpdateProgress(string step) { Messages.Clear(); Messages.Add(new Message(step)); Thread.Sleep(1000); } protected void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } }
这是因为你正在UI线程中睡觉。 在完成添加之前,UI将无法更新。 您可以将BackgroundWorker与ReportProgress一起使用来实现您的目的。 像这样的东西:
BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.DoWork += delegate(object s, DoWorkEventArgs args) { worker.ReportProgress(1, "Step1"); Thread.Sleep(1000); worker.ReportProgress(2, "Step2"); Thread.Sleep(1000); worker.ReportProgress(3, "Step3"); }; worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args) { string step = (string)args.UserState; Messages.Clear(); Messages.Add(new Message(step)); }; worker.RunWorkerAsync();
执行DoWork
时不会占用UI线程,但ProgressChanged
的代码将在UI线程上执行。
当你在UI线程上时,你永远不应该调用Thread.Sleep。 这将阻止Dispatcher并且不会渲染。 在此期间将发生绑定更新等。
如果要在UpdateProgress()调用之间等待,请使用DispatcherTimer。
您正在清除消息,然后再添加新消息。
private void UpdateProgress(string step) { Messages.Clear(); // <- Why? Messages.Add(new Message(step)); Thread.Sleep(1000); }