从外部方法更新 UI 进度条
本文关键字:UI 方法 更新 从外部 | 更新日期: 2023-09-27 18:35:38
所以这是我第一次尝试使用委托、事件、背景工作者、WPF...几乎所有东西都是新的。 我有一个运行长时间运行方法的外部类
,我想报告进度:public class ShortFileCreator
{
public void CreateShortUrlFile(string outputfilepath)
{
foreach(string line in lines)
{
//work work work processing file
if (ReportProgress != null)
{
//report progress that a file has been processed
ReportProgress(this, new ProgressArgs {TotalProcessed = numberofurlsprocessed
, TotalRecords = _bitlyFile.NumberOfRecords});
}
}
}
public delegate void ReportProgressEventHandler (object sender, ProgressArgs args);
public event ReportProgressEventHandler ReportProgress;
public class ProgressArgs : EventArgs
{
public int TotalProcessed { get; set; }
public int TotalRecords { get; set; }
}
}
在我的 WPF 窗体中,我想启动 CreateShortUrlFile 方法并更新窗体的进度栏。
private void btnRun_Click(object sender, RoutedEventArgs e)
{
var shortFileCreator = new ShortFileCreator();
_worker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
shortFileCreator.ReportProgress += ShortFileCreator_ReportProgress;
_worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
_bitlyFileWorker.CreateShortUrlFile(saveFileDialog.FileName);
};
_worker.RunWorkerAsync();
}
protected void ShortFileCreator_ReportProgress(object sender, ShortFileCreator.ProgressArgs e)
{
//update progress bar label
txtProgress.Content = String.Format("{0} of {1} Records Processed", e.TotalProcessed, e.TotalRecords);
//update progress bar value
progress.Value = (double) e.TotalProcessed/e.TotalRecords;
}
但是,当我运行它时,它会处理一行,然后我得到异常:调用线程无法访问此对象,因为另一个线程拥有它。 还有什么线程拥有这个?ReportProgress 事件不应该将 ProgressArgs 返回给任何订阅者吗?
这是因为 UI 控件(如 ProgressBar
和 TextBox
)不能被另一个线程触及,在这种情况下,您尝试从BackgroundWorker
线程更新它们。
解决此问题的一种方法是将调用Invoke
回 UI 线程,您可以使用 Dispatcher
protected void ShortFileCreator_ReportProgress(object sender, ShortFileCreator.ProgressArgs e)
{
Dispatcher.Invoke((Action)delegate
{
//update progress bar label
txtProgress.Content = String.Format("{0} of {1} Records Processed", e.TotalProcessed, e.TotalRecords);
//update progress bar value
progress.Value = (double) e.TotalProcessed/e.TotalRecords;
});
}