2016-07-27 17 views
1

以下はサンプルコードです。デベロッパーbareditItem(プログレスバー)を使用して、データがロードされたときの進行状況を表示します。 async awaitとtaskを使用して同じ進行状況バー(データがロードされているときに進行状況を表示)を表示できる方法があるかどうかを知りたい。バックグラウンドワーカーから非同期タスクを待つ

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace ProgressBar { 
    public partial class Form1 : DevExpress.XtraEditors.XtraForm { 

     DataTable workTable; 

     public Form1() { 
      InitializeComponent(); 
      workTable = new DataTable("Records"); 
      workTable.Columns.Add("Id", typeof(int)); 
      workTable.Columns.Add("Data", typeof(String)); 
     } 

     //this data varies from 0 to 50,000 rows 
     private void LoadData(DoWorkEventArgs e) { 
      for(int i = 0; i < 1001; i++) { 
       System.Threading.Thread.Sleep(5); 
       workTable.Rows.Add(i, String.Format("Record {0}", i)); 
       this.backgroundWorker1.ReportProgress(i, i); 
      } 

     } 

     private void button1_Click(object sender, EventArgs e) { 
      this.backgroundWorker1.RunWorkerAsync(); 
     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { 
      LoadData(e); 
     } 

     private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { 
      DataTable up = workTable.Clone(); 
      this.barEditItem1.EditValue = e.ProgressPercentage; 
     } 

     private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
      gridControl1.DataSource = workTable; 
     } 
    } 
} 

答えて

1

BackgroundWorkerは(非同期待つ機能のリリース以来)私にとっては時代遅れな機能です。今から使用しないでください。これは、空想的な非同期待ちを使用して同等です:

private async void button1_Click(object sender, EventArgs e) 
{ 
    await LoadData(); 
} 

private async Task LoadData() 
{ 
    for (int i = 0; i < 1001; i++) 
    { 
     await Task.Delay(5); 
     workTable.Rows.Add(i, String.Format("Record {0}", i)); 

     DataTable up = workTable.Clone(); // useless but copied from your code 
     this.barEditItem1.EditValue = i; 
    } 
    gridControl1.DataSource = workTable; 
} 
+0

BackgroundWorkerは廃止されていません。 – LarsTech

+1

@LarsTech async-awaitのリリース後には使用することはお勧めしません。 – user3185569

-1

があります。それは時代遅れのため、バックグラウンドワーカーをまったく使用しないでください。

ここにあなたの道を開くべき(テストされていない)コードがあります。 SynchronizationContextは、クロススレッド例外を防ぎます。それを行うより良い方法があるかもしれませんが、それは私が使用するものです。

namespace ProgressBar 
{ 
    using System.ComponentModel; 
    using System.Data; 
    using System.Threading; 
    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Data; 
    using System.Drawing; 
    using System.Linq; 
    using System.Text; 
    using System.Windows.Forms; 

    public partial class Form1 : DevExpress.XtraEditors.XtraForm 
    { 

     private DataTable workTable; 
     private SynchronizationContext _context; 

     public Form1() 
     { 
      InitializeComponent(); 

      this._context = SynchronizationContext.Current; 

      workTable = new DataTable("Records"); 
      workTable.Columns.Add("Id", typeof(int)); 
      workTable.Columns.Add("Data", typeof(String)); 
     } 

     private async Task LoadData() 
     { 
      const int iterations = 1001; //whatever you want... 

      for (int i = 0; i < iterations; i++) 
      { 
       workTable.Rows.Add(i, String.Format("Record {0}", i)); 
       this._context.Post(() => 
       { 
        this.UpdateWorkProgress((int) i /iterations) 
       }); 
      } 
     } 

     private void UpdateWorkProgress(int percent) 
     { 
      this.barEditItem1.EditValue = percent; 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      await this.LoadData(); 
      gridControl1.DataSource = workTable; 
     }   
    } 
} 
+0

なぜdownvote? – Brandon

1

あなたのコードは変換され、進捗レポートの更新が正しいスレッド上で発生していることを確認するためにasync/awaitパターンとProgress<T>クラスを使用して単純化することができます:私は数行のコードで左

namespace ProgressBar { 
    public partial class Form1 : DevExpress.XtraEditors.XtraForm { 

     DataTable workTable; 

     public Form1() { 
      InitializeComponent(); 
      workTable = new DataTable("Records"); 
      workTable.Columns.Add("Id", typeof(int)); 
      workTable.Columns.Add("Data", typeof(String)); 
     } 

     //this data varies from 0 to 50,000 rows 
     private void LoadData(IProgress<int> progress) { 
      for(int i = 0; i < 1001; i++) { 
       System.Threading.Thread.Sleep(5); 
       workTable.Rows.Add(i, String.Format("Record {0}", i)); 
       progress.Report(i); 
      } 
     } 

     private async void button1_Click(object sender, EventArgs e) { 
      // 1. This replaces: backgroundWorker1_ProgressChanged 
      var progress = new Progress<int>(
       i => 
       { 
       // This code will execute on the UI thread, as it should 
       DataTable up = workTable.Clone(); 
       this.barEditItem1.EditValue = i; 
       }); 

      // 2. This replaces: backgroundWorker1_DoWork 
      await Task.Run(() => this.LoadData(progress)); 

      // 3. This replaces: backgroundWorker1_RunWorkerCompleted 
      gridControl1.DataSource = workTable; 
     } 
    } 
} 

Thread.SleepDataTable up = workTable.Clone();のように、実際に必要とは思わないと思っていますが、わかりました。

+0

Ooooooh、私は 'IProgress 'について知らなかった。甘い。 – Brandon