从任务更新 ViewModel 属性

Update ViewModel property from task

我正在使用 WPF 和 Caliburn.Micro 构建应用程序。我想从 Task/Thread 更新 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 但我的代码正常工作。是不是我遗漏了某些可能会导致偶发错误的东西,或者是否有一些幕后的魔法来处理同步?

这将取决于您如何实现 INotifyPropertyChanged。实施应将所有 UI 更新委托给适当的调度程序。

实施示例:

public void RaisePropertyChanged([CallerMemberName]string name) {
        Application.Current.Dispatcher.Invoke(() => {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }, System.Windows.Threading.DispatcherPriority.Background);
    }

也开始清理任务了:

编辑: 删除了不必要的 bool return 值,并设置 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);
    }
}