2013-04-08 75 views
0

我正在執行一個使用backgroundWorker1的DLL,它通過引用更新變量i。要使用i更新進度欄,我使用以下代碼。我也想顯示文字的百分比。問題是文本(而不是進度條)閃爍了很多。我怎樣才能減少/消除這種閃爍?增加睡眠時間不是一種選擇。減少/刪除進度條內部文本的閃爍

BackgroundWorker backgroundWorker1 = new BackgroundWorker(); 
backgroundWorker1.WorkerReportsProgress = true; 
backgroundWorker1.DoWork += (s, args) => 
{ 
    Mydll.MyCFunction(ref i); 
}; 
backgroundWorker1.RunWorkerAsync(); 

while (backgroundWorker1.IsBusy) 
{ 
    backgroundWorker1.ReportProgress(i * 100);    
    backgroundWorker1.ProgressChanged += (s, e) => 
    { 
     progressBar1.Refresh(); 
     progressBar1.Value = e.ProgressPercentage; 
     progressBar1.CreateGraphics().DrawString(e.ProgressPercentage.ToString() + "%", 
      SystemFonts.DefaultFont, Brushes.Black, 
      new PointF(progressBar1.Width/2 - 10, progressBar1.Height/2 - 7)); 
    }; 
    Application.DoEvents(); 
    System.Threading.Thread.Sleep(200); 
} 

謝謝。

+0

爲什麼要叫'progressBar1.Refresh()' – 2013-04-08 09:50:43

+2

不應該訂閱ProgressChanged發生循環外? – Martheen 2013-04-08 09:52:25

+0

我懷疑你的問題是'應用程序。DoEvents();' – DGibbs 2013-04-08 09:52:26

回答

1

您的代碼會訂閱ProgressChanged事件很多次。您只需要訂閱一個事件即可。擁有所有這些事件意味着,對於每一次改變的進展,進度條上的刷新次數都會增加。

我建議創建一個單獨的事件處理程序的進展更改事件,並確保您只訂閱一次。

所以,試圖讓你的設計:

訂閱事件處理ProgressChanged(事件處理程序的其他地方聲明)

環 {

ReportProgress

的DoEvents

睡眠 }

作爲一個側面說明,你爲什麼睡覺的線程?

+0

真的不能說明爲什麼(因爲我們沒有完整的源代碼),但他可能會睡覺,否則他會放慢他的電腦。 (或者Application.DoEvents()阻止,我不這麼認爲。) – joell 2013-04-08 10:20:47

+0

我發佈了完整的bgworker代碼。 – Prometheus 2013-04-08 10:25:51

+0

我睡覺了,因爲DLL需要一段時間來執行迭代並更新'i'。 – Prometheus 2013-04-08 10:27:25

0

您的代碼有多個錯誤。其中一個,一般來說叫Application.DoEvents。這在VB6 15年前可能有用,但這是技術石器時代。您還將同一個處理程序多次附加到事件中,這意味着在100次循環之後,您的繪圖將被稱爲每百分比100次。

有這麼多的錯誤,很難建議一個簡單的修復。看看here兩種簡單的方法來完成這項工作。嘗試瞭解發生了什麼,以什麼順序以及爲什麼。

0

首先,我會刪除行Application.DoEvents();(有關事件的出色post),這通常表示不良的多線程設計。我也會親自去掉Thread.Sleep電話。

其次,您應該訂閱工作循環的外部ProgressChanged。例如:

public Form1() 
{ 
    bgWorker.ProgressChanged += bgWorker_ProgressChanged; 
} 

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    progressBar.Value = e.ProgressPercentage; 
    progressBar1.CreateGraphics().DrawString(e.ProgressPercentage.ToString() + "%", 
      SystemFonts.DefaultFont, Brushes.Black, 
      new PointF(progressBar1.Width/2 - 10, progressBar1.Height/2 - 7)); 
} 
+0

當我在while(backgroundWorker1.IsBusy)循環之外保留'ProgressChanged'時,progrss欄不會更新。 – Prometheus 2013-04-08 10:13:18

+0

也刪除'while(backgroundWorker1.IsBusy)'塊。只需通過該方法即可調用報告進度。既然你沒有發佈完整的do_work方法,但我不能肯定地說。 – DGibbs 2013-04-08 10:15:13

+0

我已經用'Do.Work'更新了原文。 – Prometheus 2013-04-08 10:17:52

2

如果圖形閃爍,則應啓用雙緩衝。

DoubleBuffered = true 

或者

SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 

欲瞭解更多信息:http://msdn.microsoft.com/en-us/library/3t7htc9c.aspx

+0

做到了。沒有幫助。 – Prometheus 2013-04-08 10:24:39

+0

不是我關心代表什麼的,而是那些低調至少解釋爲什麼我會從我的缺點中學習的人。 – joell 2013-04-08 12:18:32