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 线程上调用的。
在我的 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 线程上调用的。