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();
    }
}

c# ProgressBar Databindings在后台工作

数据绑定应该在构造函数中创建,因为您只需要创建一次绑定,而不是每次都需要:

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。调用以更新控件属性。关于这个问题的问题:数据绑定在多线程应用程序?