c# ProgressBar Databindings在后台工作
本文关键字:后台 工作 Databindings ProgressBar | 更新日期: 2023-09-27 18:16:33
我不是c#专家,但我想做的是在后台工作器中更新进度条。我使用下面的代码:
progressBar1.DataBindings.Add("Value", _dm, "Progress", true,
DataSourceUpdateMode.OnPropertyChanged);
在没有后台工作线程的GUI线程上执行时有效。Progress属性是一个属性,更新(使用INotifyPropertyChanged)从另一个后台工作者(我没有访问)的进度。
我怎么能使它的工作,使它更新使用后台工作者,而不是把它全部放在GUI线程?
我的代码(简化):
class DownloadManager : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private double _progressValue;
public double Progress
{
get { return _progressValue; }
private set
{
if (!value.Equals(_progressValue))
{
_progressValue = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Progress"));
}
}
}
public void Download()
{
var downloader = new Downloader();
downloader.DownloadProgressChanged += (sender, e)
=> Progress = e.ProgressPercentage;
downloader.Execute();
}
}
public partial class MainForm
{
private readonly DownloadManager _dm;
public MainForm()
{
InitializeComponent();
_dm = new DownloadManager();
}
private void btnDownload_Click(object sender, EventArgs e)
{
//TRIED HERE ...
progressBar1.DataBindings.Add("Value", _dm, "Progress", true,
DataSourceUpdateMode.OnPropertyChanged);
bwDownload.RunWorkerAsync();
}
}
private void bwDownload_DoWork(object sender, DoWorkEventArgs e)
{
//AND TRIED HERE
progressBar1.DataBindings.Add("Value", _dm, "Progress", true, DataSourceUpdateMode.OnPropertyChanged);
//THIS AINT WORKING EITHER
if (progressBar1.InvokeRequired) {
progressBar1.Invoke(new MethodInvoker(()
=> progressBar1.DataBindings.Add("Value", _dm, "Progress", true,
DataSourceUpdateMode.OnPropertyChanged)));
}
_dm.Download();
}
}
数据绑定应该在构造函数中创建,因为您只需要创建一次绑定,而不是每次都需要:
public MainForm()
{
InitializeComponent();
_dm = new DownloadManager();
progressBar1.DataBindings.Add("Value", _dm, "Progress", true, DataSourceUpdateMode.OnPropertyChanged);
}
你的代码不工作,因为你试图从非UI线程更新UI。您需要将代码包装在Invoke()
调用中,例如在Form上使用代理属性:
public partial class MainForm
{
private double _progress;
public double Progress
{
get { return _progress; }
set
{
_progress = value;
// If not in the UI thread -> wrap the update in an Invoke() call:
if (this.InvokeRequired)
{
this.Invoke(new Action(() => progressBar1.Value = (int) _progress), new object[] { });
return;
}
// Else update directly
progressBar1.Value = (int) value;
}
}
private readonly DownloadManager _dm;
public MainForm()
{
InitializeComponent();
_dm = new DownloadManager();
// Bind _db.Progress <-> this.Progress
DataBindings.Add("Progress", _dm, "Progress", true, DataSourceUpdateMode.OnPropertyChanged);
}
GUI元素需要在UI线程中更新。你需要使用Control。调用以更新控件属性。关于这个问题的问题:数据绑定在多线程应用程序?