在我的WPF应用程序中,我有一个ProgressBar,我想根据另一个类的方法中的进度动态设置它的Value
属性。然而,我不确定如何做到这一点。
做这项工作的类和方法如下:
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.cs类中,关注的方法是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>
报告进度,使用Task.Run
将处理转移到后台线程。
如果不将处理转移到后台线程,则会发生在UI线程上。这意味着UI线程正忙于处理您的事务,因此无法更新进度条(并且您的应用程序将显示为冻结状态(。
Progress<T>
允许您使用相应IProgress<T>
接口上的Report
方法来定义每次报告进度时调用的操作,我们将使用该方法来更新进度条。它还确保无论在哪个线程上调用其Report
方法,都会在UI线程1上调用此操作。这意味着从后台线程调用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螺纹上调用的。