2016-11-05 11 views
2

私はC#の専門家はいませんが、私がやっていることは、バックグラウンドワーカーのプログレスバーを更新することです。私は次のコードを使用しています:C#ProgressBarデータバインディングbackgroundworker

これは、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(); 
    } 
} 

答えて

2

データ・バインディングは、あなたのコンストラクタで作成する必要がありますUIを非UIスレッドから更新します。フォーム上のプロキシプロパティを使用して、例えば、Invoke()呼び出しでコードをラップする必要がある必要があります。

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

GUI要素は、UIスレッドで更新する必要があります。コントロールのプロパティを更新するには、Control.Invokeを使用する必要があります。この問題についてモーラ:

public MainForm() 
{ 
    InitializeComponent(); 
    _dm = new DownloadManager(); 
    progressBar1.DataBindings.Add("Value", _dm, "Progress", true, DataSourceUpdateMode.OnPropertyChanged); 
} 

あなたのコードが動作していないあなたがしようとするため:あなたは一度だけではなく、それが必要なのたびにバインディングを作成する必要があるとして、Data Binding on multi thread application?

+0

は作業のいずれか..私は私の簡素化コードにそれを追加するのを忘れていないです – JC97

関連する問題