2012-06-18 56 views
3

我有一個帶接口的庫。進度條工作但標籤沒有更新

Public Interface Progress 
{ 
    int ProgressValue{get;set;}, 
    string ProgressText{get;set;}, 
} 

圖書館有一個方法創建(啞代碼):

Public Class TestLibrary 
{ 

    Progress _progress; 

    Public void Create() 
    { 
     foreach(var n in TestList) 
     { 
      // Do Something 
      _progress.ProgressValue = GetIndex(n); 
      _progress.ProgressText = "Updating..." + n; 
     } 
    } 
} 

我有一個項目引用該庫並調用Create方法。它甚至實現了界面進度。

Public Class TestProject : Progress 
{ 
    public int ProgressValue 
    { 
     get{return progressBar1.Value;} 
     set{progressBar1.Value = value;} 
    } 

    public int ProgressText 
    { 
     get{return label1.Text;} 
     set{label1.Text = value;} 
    } 
} 

現在,當我運行應用程序,進度條正確的行爲,正確地顯示了進展,但Label1文本並沒有改變。但它在for循環結束時會改變,並顯示循環中的最後一項。任何人都可以幫我解決這個問題嗎?

注意:所有這些代碼都是直接寫入,沒有測試,因爲我現在沒有我的應用程序。對不起,任何語法錯誤。

+1

是否改變*時,它的完成*出於興趣?如果是這樣,這可能只是一個線程問題 - 看起來你在UI線程中做了太多工作。 –

+0

@JonSkeet:是的,它會改變。我編輯了這個問題以反映相同的問題。 – Sandy

+0

這肯定是一個線程問題 - 確保您的「進度」代碼不會在UI線程上運行 – Carsten

回答

5

使用了Label instead of ProgressBar。你可以試試這個代碼[using BackGroundWorker] -

using System.ComponentModel; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form3 : Form 
    { 
     private BackgroundWorker _worker; 
     BusinessClass _biz = new BusinessClass(); 
     public Form3() 
     { 
      InitializeComponent(); 
      InitWorker(); 
     } 

     private void InitWorker() 
     { 
      if (_worker != null) 
      { 
       _worker.Dispose(); 
      } 

      _worker = new BackgroundWorker 
      { 
       WorkerReportsProgress = true, 
       WorkerSupportsCancellation = true 
      }; 
      _worker.DoWork += DoWork; 
      _worker.RunWorkerCompleted += RunWorkerCompleted; 
      _worker.ProgressChanged += ProgressChanged; 
      _worker.RunWorkerAsync(); 
     } 


     void DoWork(object sender, DoWorkEventArgs e) 
     { 
      int highestPercentageReached = 0; 
      if (_worker.CancellationPending) 
      { 
       e.Cancel = true; 
      } 
      else 
      { 
       double i = 0.0d; 
       int junk = 0; 
       for (i = 0; i <= 199990000; i++) 
       { 
        int result = _biz.MyFunction(junk); 
        junk++; 

        // Report progress as a percentage of the total task. 
        var percentComplete = (int)(i/199990000 * 100); 
        if (percentComplete > highestPercentageReached) 
        { 
         highestPercentageReached = percentComplete; 
         // note I can pass the business class result also and display the same in the LABEL 
         _worker.ReportProgress(percentComplete, result); 
         _worker.CancelAsync(); 
        } 
       } 

      } 
     } 

     void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if (e.Cancelled) 
      { 
       // Display some message to the user that task has been 
       // cancelled 
      } 
      else if (e.Error != null) 
      { 
       // Do something with the error 
      } 
     } 

     void ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      label1.Text = string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage); 
     } 
    } 

    public class BusinessClass 
    { 
     public int MyFunction(int input) 
     { 
      return input+10; 
     } 
    } 
} 

發佈相同的前幾天here

+0

謝謝....讓我試試這個,一旦我到我的筆記本電腦 – Sandy

+0

很酷...它是一個合理的/標準的方式來實現Winforms世界使用backgroundworker這樣的任務。 –

8

聽起來你所有的工作都是在UI線程上完成的。不要這樣做。

相反,運行在後臺線程循環本身,並使用Control.InvokeControl.BeginInvoke(可能在Progress實現)跨封送調用UI線程只是爲了更新UI。這將使你的UI響應(並且能夠更新標籤等),同時它仍在處理中。

+0

謝謝....讓我試試這個,一旦我到我的筆記本電腦 – Sandy

+0

我接受了這個答案,我對這些東西沒有太多的瞭解......經過一定的經驗和知識,現在我可以清楚地看到你在嘗試指出。謝謝:) – Sandy