2013-07-11 133 views
4

我是新來的使用事件處理程序和背景工作者,所以我可能會錯過這裏完全明顯的東西。不過,我一直試圖解決這個問題兩天,所以我想我不妨看看有什麼人說。Backgroundworker總是忙碌

我有一個名爲SqlExpressDownloader的背景工作器。它開始在我的程序開始時運行,其餘的工作運行,然後在繼續之前它應該等待SqlExpressDownloader_DoWork()方法中的操作完成。唯一的問題是,由於某種原因,每當我做while(SqlExpressDownloader.IsBusy),它總是響應忙碌,因此將永遠等待。

事件處理程序的代碼是在這裏:

private void SqlExpressDownloader_DoWork(object sender, DoWorkEventArgs e) 
    { 
     string sSource = string.Format("{0}\\{1}", Paths.Settings_Common, "sqlexpr_x64_enu.exe"); 
     Debug.WriteLine(sSource); 
     Debug.WriteLine("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe"); 
     if (!System.IO.File.Exists(sSource)) 
     { 
      WebClient oWebClient = new WebClient(); 
      oWebClient.DownloadProgressChanged += DownloadProgressChanged; 
      oWebClient.DownloadDataCompleted += DownloadComplete; 

      oWebClient.DownloadFileAsync(new System.Uri("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe"), sSource); 

      while (oWebClient.IsBusy) 
      { 
       Thread.Sleep(100); 
      } 

      e.Result = ""; 
      DownloadFinished = true; 
     } 
    } 

我看過的代碼,都看過了完成此方法。我甚至在DownloadFinished = true之後加了return,但它仍然很忙。我想知道的是如何讓背景工作者不忙。

編輯 事件在構造函數中添加的所有如下所示:

 SqlExpressDownloader = new BackgroundWorker(); 
     SqlExpressDownloader.DoWork += new DoWorkEventHandler(this.SqlExpressDownloader_DoWork); 
     SqlExpressDownloader.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.SqlExpressDownloader_RunWorkerCompleted); 

RunWorkerCompleteEventHandler看起來是這樣的:

private void SqlExpressDownloader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Error != null) 
     { 
      Debug.WriteLine("The actions are complete."); 
     } 
     else 
     { 
      Debug.WriteLine("Error in completed work."); 
     } 
    } 

但是,當我最後調試它,它沒有實際上觸發。

+0

你是怎麼開始工作的? – Patrick

+0

在主要方法中,我使用'SqlExpressDownloader.RunWorkerAsync()'開始它。 – ijb109

+0

檢查工作者的IsBusy時,是否使用了類似於方法主體中的while循環?方法完成後,RunWorkerCompleted事件是否觸發? – Patrick

回答

1

你可以用更優雅的異步替換您的代碼/等待這樣

private async Task SqlExpressDownloadAsync() 
{ 
    string sSource = string.Format("{0}\\{1}", Paths.Settings_Common, "sqlexpr_x64_enu.exe"); 
    Debug.WriteLine(sSource); 
    Debug.WriteLine("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe"); 
    if (!System.IO.File.Exists(sSource)) 
    { 
     WebClient oWebClient = new WebClient(); 
     oWebClient.DownloadProgressChanged += DownloadProgressChanged; 
     oWebClient.DownloadDataCompleted += DownloadComplete; 
     await oWebClient.DownloadFileTaskAsync(new System.Uri("http://www.elexioamp.com/Install/redistributables/sql2008r2express/sqlexpr_x64_enu.exe"), sSource); 
    } 
} 
+0

我對任務不熟悉。我能跟蹤下載的進度,就像我在後臺工作中使用事件處理程序一樣嗎?我的項目中涉及到一個GUI組件。我會試試這個。 – ijb109

+0

儘管此時此刻不運行異步。你應該把它包裝在一個task.run – Patrick

+0

絕對!我添加了缺少的事件句柄,它們會像您的代碼一樣觸發。 –

3

而是在一個循環中查詢SqlExpressDownloader.IsBusy的解決方案,嘗試訂閱到RunWorkerCompleted事件BackgroundWorker的,把你的代碼在那裏,應該只有在DoWork事件完成後纔會發生。

您還可以訪問RunWorkerCompletedEventArgs,您可以檢查以確保您的BackgroundWorkerDoWork部分沒有錯誤。

... 
    ... 
    SqlExpressDownloader.RunWorkerCompleted += SqlExpressDownloader_RunWorkerCompleted; 
    SqlExpressDownloader.RunWorkerAsync(); 
} 

private void SqlExpressDownloader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (e.Error != null) 
    { 
     // do something in response to the error 
    } 

    // stuff to do after DoWork has completed 
} 

我發現Joe Albahari's tutorial幫助時,我正在學習如何使用這些。

1

我有類似的問題。 DownloadASync會觸發,但.IsBusy將始終保持真實。

這可能不會是一個常見問題,只是想我分享我的決議。

我用

MessageBox.Show(new Form() { TopMost = true }, "", "") 

這是原因。我也試過:

var t = new Form() { TopMost = true }; 
MessageBox.Show(t, "", ""); 
t.Dispose(); 

這引起了同樣的問題。我的代碼有多個線程,我假設其中一個必須被卡住,或者MessageBox(新的Form(){TopMost = true;})調用創建了一個卡住的線程。

只要我刪除那部分,例如。

MessageBox.Show("", ""); 

一切都按預期再次運作。

所以,也許你正在創造另一個線程,導致你的問題。