2011-11-01 109 views
2

我正在嘗試更新主窗體上的進度條,並在不同的類中完成工作。例如:C#,使用不同類別的後臺工作人員更新進度欄

private void transfer_Click(object sender, EventArgs e) 
{ 
    Guid aspnetUserId = Guid.Parse(System.Configuration.ConfigurationSettings.AppSettings["ASPNetUserID"]); 
    WC1toWC2Transfer transfer = new WC1toWC2Transfer(aspnetUserId); 

    backgroundWorker1.RunWorkerAsync(transfer); 
} 

然後在後臺方法實際上調用方法:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    WC1toWC2Transfer transfer = e.Argument as WC1toWC2Transfer; 
    transfer.WC1ToWC2EmployerTransfer(log, wc1ConnStr, wc2ConnStr, progressBar1); 
} 

在WC1ToWC2EmployerTransfer方法,我設置了進度條的最大值和更新值每次的東西轉移到在這個方法中的數據庫,但是當我這樣做時沒有任何反應。在數據庫中運行存儲過程的方法中有代碼,但只要它碰到那部分代碼,它就停止調試,我必須再次運行該過程。

我在這裏做錯了什麼?我是否需要重寫我擁有的所以實際方法是以主要形式存在,而不是在不同的班級中?我是一名初級開發人員(幾個月前剛開始),所以如果我正在做一些明顯錯誤的事情,或者我沒有足夠好地解釋這件事,請原諒我。

任何幫助將不勝感激。

+1

不確定這是關於什麼,但你一定要排除故障「停止調試」。 BackgroundWorker吞下異常並將它們傳遞給具有e.Error屬性的RunworkerCompleted事件處理程序。一些你不想忽視的東西。最好的方法是不要忽略它,使用Debug + Exceptions,爲CLR異常勾選Thrown複選框。 –

回答

2

你不能改變用戶界面,除非你在主線程上,而你的BackgroundWorker不會。

您需要做的是在主窗體中創建一個事件處理函數來處理backgroundworker的ProgressChanged事件。

// this method should be in your main form. 
private void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // update your progress bar here. 
} 

在你的後臺工作,你叫ReportProgress方法,將觸發ProgressChanged事件。

有一個很好的例子here

1

我認爲原因是你得到一個IllegalCrossThreadException,因爲你試圖從一個不同的線程訪問控件,而不是它創建的。 BackgroundWorker提供了一個ReportProgress方法和一個ProgressChanged事件,它通常用於這種更新,並將在UI線程上執行。當訪問從另一個線程比UI線程的進度,像這樣做:

if(progressBar1.InvokeRequired) { 
    progressBar1.Invoke(new MethodInvoker(delegate { progressBar1.Maximum = someValue; })); 
} 

一點題外話:這不是很好的設計的進度傳遞給你的工人階級。表格可能會關閉,可能會被處置,工作人員也不會知道任何事情,最終會失敗,可能不會被抓到。此外,如果工作人員可能不需要,工作人員依賴於System.Windows.Forms。而是讓您的工作人員通過事件報告進度,並將其傳遞到創建該工作人員的類的進度條上。

+1

另外,如果你有興趣,[進步](https://github.com/scottrippey/Progression/wiki)(免責聲明:我寫了它)是一個非常簡單的進度計算庫,允許你的工作方法正確報告進步,而不知道UI的任何內容。要麼UI訂閱線程安全事件,要麼'BackgroundWorker'可以訂閱並報告事件。 –