我正在使用WPF和Caliburn.Micro构建应用程序。我想从任务/线程更新ProgressBar,我想知道我需要正确更新UI:
public class DemoViewModel : PropertyChangedBase
{
private int m_Progress;
public int Progress
{
get { return m_Progress; }
set
{
if (value == m_Progress) return;
m_Progress = value;
NotifyOfPropertyChange();
NotifyOfPropertyChange(nameof(CanStart));
}
}
public bool CanStart => Progress == 0 || Progress == 100;
public void Start()
{
Task.Factory.StartNew(example);
}
private void example()
{
for (int i = 0; i < 100; i++)
{
Progress = i + 1; // this triggers PropertChanged-Event and leads to the update of the UI
Thread.Sleep(20);
}
}
}
从其他编程语言我知道我需要与UI线程同步以更新UI,但我的代码才有效。是否有我遗漏的东西,哪些可能导致零星错误,或者是否有一些关注同步的幕后魔术?
答案 0 :(得分:2)
这取决于您实施INotifyPropertyChanged的方式。实现应该将所有UI更新删除到适当的调度程序。
示例实施:
public void RaisePropertyChanged([CallerMemberName]string name) {
Application.Current.Dispatcher.Invoke(() => {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}, System.Windows.Threading.DispatcherPriority.Background);
}
还要开始清理任务:
修改强>
删除了不必要的bool返回值,并设置ConfigureAwait
以在任务完成时保持关闭UI线程。
public async void Start()
{
await Task.Run(() => example()).ConfigureAwait(false);
}
private async Task example()
{
for (int i = 0; i < 100; i++)
{
Progress = i + 1; // this triggers PropertChanged-Event and leads to the update of the UI
await Task.Delay(20);
}
}