2016-07-27 36 views
1

下面是示例代碼,它使用devexpress bareditItem(progressbar)來顯示加載數據時的進度。我想知道是否有一種方法可以使用異步等待和任務顯示相同的進度條(顯示數據加載時的進度)。後臺工作者異步等待任務

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不推薦在異步等待發布後使用。 – 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