2011-12-21 61 views
3

我注意到,隨着我的應用程序數據庫的增長,返回結果所花的時間也增加了。在開始時這是微不足道的,因爲返回數據源的時間很少。是否有可能爲後臺工作人員提供一種通用方法?

現在我處於臨時讓UI停止響應幾秒的時間點,但我想創建background workers來完成這些任務。

創建這些的問題是,有大約9個按鈕需要後臺工作人員,他們所做的只是在DLL中調用不同的方法。有沒有辦法使用通用方法爲後臺工作人員使用API​​創建這些後臺工作人員,還是應該創建與每個按鈕相對應的Enum,並且是構造後臺工作人員的方法所採用的參數。因此,我可以使用簡單的switch來執行我選擇的DLL中的任何方法?

示例代碼:

void bg_DoWorkImports(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = sender as BackgroundWorker; 

     try 
     { 
      e.Result = EngineBllUtility.GetNotImportedFiles(connectionString); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 

    void bg_RunWorkerCompletedImports(object sender, RunWorkerCompletedEventArgs e) 
    { 
     DataSet temp = (DataSet)e.Result; 
     if (e.Result != null) 
     { 
      importFileGridView.DataSource = temp.Tables[0]; 
     } 
    } 
+0

你使用的是.NET 4嗎?對於這種類型的場景,TPL是BackgroundWorker的一個很好的替代方案... – 2011-12-21 18:44:24

+0

不幸的是,.NET 3.5 – ediblecode 2011-12-21 18:45:22

+0

將對Rx框架進行依賴是一個選擇,因爲它會讓你獲得TPL嗎? http://msdn.microsoft.com/en-us/data/gg577610 – 2011-12-21 18:46:56

回答

2

您可以將Func<T>傳遞給創建BackgroundWorker並將該操作從內部調用到DoWork事件的方法。

像這樣的事情

public class BackgroundWrapper<T> 
{ 
    private Func<T> workMethod; 
    private Action<T> completeMethod; 
    public static void StartBackgroundworker(Func<T> workMethod, Action<T> completeMethod) 
    { 
     BackgroundWrapper<T> bWrap = new BackgroundWrapper<T>(); 
     bWrap.workMethod = workMethod; 
     bWrap.completeMethod = completeMethod; 
     bWrap.Start(); 
    } 

    private void Start() 
    { 
     BackgroundWorker bw = new BackgroundWorker(); 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
     bw.RunWorkerAsync(); 
    } 

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     completeMethod((T)e.Result); 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     e.Result = workMethod(); 
    } 
} 
+0

謝謝阿爾賓,我會探討這種方法。 – ediblecode 2011-12-21 18:27:20

+2

你基本上重新創建了'System.Threading.Tasks'命名空間中的功能。使用正確的工具進行工作; 'BackgroundWorker'可能不是這裏的正確工具。 – 2011-12-21 18:33:17

+1

@AdamRobinson這基本上就是我的想法 - 如果你要通過這個,你可以使用TPL,這在很多方面都更好用...... – 2011-12-21 18:44:05

0

我認爲你需要建立某種形式的隊列機制,其中一個背景工人拿起每一個點擊按鈕的工作和其他後揭開序幕之一。

+0

庫馬爾,這將是一個不受歡迎的功能 – ediblecode 2011-12-21 18:20:58

1

當然,我不明白爲什麼你不能創建一個「交換機」類的功能。事實上,你可能想這樣做,因爲它會使事情變得更加模塊化並促進代碼重用。

就enums而言,個人而言,我創建了類來傳遞大量的參數。

2

而不是使用的BackgroundWorker的,另一種是使用第三方物流。這會讓你直接在每個成員內編寫代碼:

void buttonImport_Click(object sender, DoWorkEventArgs e) 
{ 
    Task.Factory 
     .StartNew(() => return EngineBllUtility.GetNotImportedFiles(connectionString)) 
     .ContinueWith(t => 
    {   
     try 
     { 
      if (t.Result != null) 
      { 
       importFileGridView.DataSource = t.Result.Tables[0]; 
      } 
     } 
     catch (AggregateException ex) 
     { 
      MessageBox.Show(ex.InnerException.Message); 
     } 
    }, TaskScheduler.FromCurrentSynchronizationContext()); 
}