WPF - 如何根据来自不同 class 的方法的进度更新 ProgressBar?

WPF - How to update ProgressBar based on the progress of a method from a different class?

在我的 WPF 应用程序中,我有一个 ProgressBar,我想为其动态设置 Value 属性,具体取决于另一个 class 方法中取得的进展.但是我不确定该怎么做。

class 和完成这项工作的方法是:

public class WorkerClass
{
    public void doSomething(string filePath)
    {
        using (var package = new Package(filePath)) 
        {
            foreach (var item in package) 
            {
                updateMethod(item); //once this method call is complete I want the ProgressBar to update its Value
            }
        }
    }
}

MainWindow.xaml.csclass内,关注的方法是button_Click()方法:

private void btnUpload_Click(object sender, RoutedEventArgs e)
{
    progressBar.Value = 10;

    WorkerClass worker = new WorkerClass();
    worker.doSomething(txtFilePath.Text); //I want the ProgressBar value to update during this method execution

    progressBar.Value = 100;    
}

我尝试使用 async/await 关键字,将其应用于 doSomething() 方法并返回一个 Task<int> 对象和应用 progressBar.Value = await doSomething() 但 ProgressBar 仍然同步更新。

使用 Progress<T> to report progress, and Task.Run 将处理移动到后台线程。

如果您不将处理移动到后台线程,它将发生在 UI 线程上。这意味着 UI 线程正忙于您的处理,因此无法更新进度条(您的应用程序将出现冻结)。

Progress<T> 允许您使用 Report method on the corresponding IProgress<T> 接口定义每次报告进度时调用的操作,我们将使用该接口更新进度条。它还确保在 UI thread1 上调用此操作,而不管在哪个线程上调用其 Report 方法。这意味着从我们的后台线程调用 Report 是安全的,我们的进度条仍然会从 UI 线程更新。

public class WorkerClass
{
    public void doSomething(string filePath, IProgress<int> progress)
    {
        using (var package = new Package(filePath)) 
        {
            foreach (var item in package) 
            {
                updateMethod(item); //once this method call is complete I want the ProgressBar to update its Value
                progress.Report(...);
            }
        }
    }
}

private async void btnUpload_Click(object sender, RoutedEventArgs e)
{
    progressBar.Value = 10;

    var progress = new Progress<int>(x => progressBar.Value = x);

    string filePath = txtFilePath.Text;
    WorkerClass worker = new WorkerClass();
    await Task.Run(() => worker.doSomething(filePath, progress));

    progressBar.Value = 100;    
}

1严格来说,它在构造时捕获当前 SynchronizationContext,并在调用传递给其构造函数的 Action 时使用它。如果它是在 UI 线程上构造的,这意味着该 Action 是在 UI 线程上调用的。