2012-10-21 92 views
1

我是C#的新手,並試圖圍繞面向對象的編程思考。這是我想要實現的:BackgroundWorker ProgressChanged從一個單獨的類觸發的形式

我有一個Windows Form應用程序與Form1和一個名爲connect(同名空間)的單獨類。

據我所知,在執行冗長的代碼量時(以免凍結UI),使用backgroundworkers是一種很好的做法。所以我在Form1中創建了一個後臺工作器和一個progresschanged句柄。我試圖找到如何在單獨的連接類,我可以觸發progresschange。在Form1的progresschange塊中,我有一個case/switch,它決定了屏幕上顯示的文本。

什麼是接近最好的方法?我應該把背景工作者交給其他班級嗎?

+0

爲什麼要在連接類上處理progress_changed? –

+0

連接類運行通過一些事情,如連接到一個SQL服務器,運行一個或兩個查詢。我希望能夠最終更改form1上的statusstrip標籤以反映當前正在發生的事情(例如顯示連接到服務器,運行查詢等)。如果我可以使用另一種不鎖定用戶界面的方法從連接類更新form1上的statusstrip標籤,那麼我就是爲了它。 –

回答

2

您可以將連接類的步驟分解爲單獨的方法,並按以下順序調用它們。您不必從連接類對象觸發progresschanged事件。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    ConnectClass conObject= new ConnectClass(); 
    backgroundWorker.ReportProgress(30, "Connecting ..."); 
    conObject.Connect(); 
    backgroundWorker.ReportProgress(30, "Connected."+"\n Executing query"); 
    conObject.Execute(); 
    backgroundWorker.ReportProgress(40, "Execution completed."); 
} 
+0

ReportProgress int參數每次都必須是不同的值嗎?我看到第一個和第二個具有相同的int - 背景工作者是否認識到有變化,因爲它只是再次調用? –

+0

int表示正在完成的工作的百分比。所有的taks應該總計爲100.Andbackchanged事件將由ReportProgress調用觸發。您將必須捕獲在progress_changed事件中通過ReportProgress調用傳遞的消息並更新在狀態欄上相應的消息 –

+0

聽起來不錯 - 謝謝! –

5

您還可以將您的BackgroundWorker放置在Connect類中。在這個類中,您可以創建事件來將進度和完成情況報告給調用表單。

using System; 
using System.ComponentModel; 

namespace WindowsTest 
{ 
public class Connect 
{ 
    BackgroundWorker bw; 
    public Connect() 
    { 
     bw = new BackgroundWorker(); 
     bw.WorkerSupportsCancellation = true; 
     bw.WorkerReportsProgress = true; 
     bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
     bw.DoWork +=new DoWorkEventHandler(bw_DoWork); 
     bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 
    } 

    public delegate void ProgressChangedHandler(Object sender, ProgressChangedEventArgs e); 
    public event ProgressChangedEventHandler ProgressChanged; 
    protected void RaiseProgressChangedEvent(ProgressChangedEventArgs e) 
    { 
     if (ProgressChanged == null) 
     { 
      return; 
     } 
     ProgressChanged(this, e); 
    } 

    public delegate void WorkCompleteEventHandler(Object sender, RunWorkerCompletedEventArgs e); 
    public event WorkCompleteEventHandler WorkComplete; 
    protected void RaiseWorkCompleteEvent(RunWorkerCompletedEventArgs e) 
    { 
     if (WorkComplete == null) 
     { 
      return; 
     } 
     WorkComplete(this, e); 
    } 

    public void Cancel() 
    { 
     if (bw.IsBusy) 
     { 
      bw.CancelAsync();    
     } 
    } 

    public void BeginLongRunningProcess() 
    { 
     bw.RunWorkerAsync(); 
    } 

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     RaiseWorkCompleteEvent(e); 
    } 

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     RaiseProgressChangedEvent(e); 
    } 

    private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     if (ConnectToServer()) 
     { 
      bw.ReportProgress(0, "Connected to server"); 
      e.Result = LongRunningProcess(); 
      if (e.Result.ToString() == "Cancelled") 
      { 
       e.Cancel = true; 
       return; 
      } 
     } 
     else 
     { 
      //Connection failed 
      e.Cancel = true;  
     } 
    } 

    private bool ConnectToServer() 
    { 
     //Attempt connection 
     return true; 
    } 

    private string LongRunningProcess() 
    { 
     int recordCount = 250; 
     for (int i = 0; i <= recordCount; i++) 
     { 
      if (bw.CancellationPending) 
      { 
       return "Cancelled"; 
      } 
      double progress = ((double)i/(double)recordCount) * 100; 
      bw.ReportProgress((int)progress , "Running Process"); 
      System.Threading.Thread.Sleep(25); 
     } 
     return "The result is 2"; 
    } 
} 
} 

然後在窗體上,您只需處理事件。

namespace WindowsTest 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    Connect connect; 

    private void btnConnect_Click(object sender, EventArgs e) 
    { 
     connect = new Connect(); 
     connect.ProgressChanged += new ProgressChangedEventHandler(connect_ProgressChanged); 
     connect.WorkComplete += new Connect.WorkCompleteEventHandler(connect_WorkComplete); 
     connect.BeginLongRunningProcess(); 
    } 

    private void connect_WorkComplete(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Cancelled) 
     { 
      lblStatus.ForeColor = Color.Red; 
      lblStatus.Text = string.Format("Status: {0}", "User Cancelled!"); 
      return; 
     } 

     if (e.Error != null) 
     { 
      //Process exception  
      lblStatus.Text = string.Format("Status: {0}", "Error!"); 
      lblStatus.ForeColor = Color.Red; 
      return; 
     } 

     lblStatus.Text = string.Format("Status: Complete. {0}", e.Result); 
    } 

    private void connect_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     progressBar1.Value = e.ProgressPercentage; 
     lblStatus.Text = string.Format("Status: {0}", e.UserState.ToString()); 
    } 

    private void btnCancel_Click(object sender, EventArgs e) 
    { 
     if (connect != null) 
     { 
      connect.Cancel(); 
     } 
    }   
} 
} 

注意,第二參數的BackgroundWorker.ReportProgress的(UserState)()方法可以通過任何對象。它不一定是一個字符串。例如,如果您從數據庫檢索到一行/多行,則可以通過此方法將該行傳回給用戶界面。 BackgroundWorker.DoWork方法的e.Result也是如此。

Eric

+0

謝謝!我也會看看這個 –

相關問題