从任务更新ViewModel属性

时间:2017-02-08 14:48:03

标签: wpf mvvm caliburn.micro

我正在使用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,但我的代码才有效。是否有我遗漏的东西,哪些可能导致零星错误,或者是否有一些关注同步的幕后魔术?

1 个答案:

答案 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);
    }
}