2010-09-16 46 views
3

在C#,windows窗體中創建.net應用程序。如何在100循環循環的每個循環中更新進度條1步? (我正在處理循環中的Excel工作表。) 進度條控件位於UI類中,它連接到連接到自定義類 (MVC模式)的控制器類。循環在自定義類中。 我是否需要在每種方法中一直髮送UI類實例還是有更好的方法?如何在每個循環週期內一步更新進度條? C#

當前進度條在循環結束後更新。 Application.doevents和.update或.refresh不起作用。

+2

在較低級別的活動發佈廣告進展情況時出現了什麼問題? – Joey 2010-09-16 13:38:58

+0

對不起,我不明白你剛剛說的。進度條被定義在一個更高的類中,如果我更新低級類的值,上層類將如何知道?我不得不將ui類實例或進度條實例傳遞到較低級別。 – 2010-09-16 13:45:46

+0

我不確定,但如果更新發生延遲,它幾乎聽起來像是一個線程問題。你在使用invoke嗎(如果有必要)? – 2010-09-16 13:49:19

回答

5

說下面是你的類負責做循環工作。添加一個事件來指示你的進度。然後從你的用戶界面簡單地處理該事件並相應地更新進度條。

sealed class Looper 
{ 
    public event EventHandler ProgressUpdated; 

    private int _progress; 
    public int Progress 
    { 
     get { return _progress; } 
     private set 
     { 
      _progress = value; 
      OnProgressUpdated(); 
     } 
    } 

    public void DoLoop() 
    { 
     _progress = 0; 
     for (int i = 0; i < 100; ++i) 
     { 
      Thread.Sleep(100); 
      Progress = i; 
     } 
    } 

    private void OnProgressUpdated() 
    { 
     EventHandler handler = ProgressUpdated; 
     if (handler != null) 
     { 
      handler(this, EventArgs.Empty); 
     } 
    } 
} 

你可能會被具有BackgroundWorker爲你的用戶界面,其中在backgroundWorker.DoWork事件調用looper.DoLoop()的一部分實現這一點。然後在looper.ProgressUpdated事件的處理程序中,您可以調用backgroundWorker.ReportProgress來從UI線程增加進度條。

請注意,在您的ProgressUpdated事件所攜帶的信息中包含進度本身可能更有意義(我只是不想寫出來自EventArgs的新類來說明這一點;您可能會得到圖片無論如何)。

另請注意,除非您正在使用UI線程的單獨線程上的循環執行代碼,否則上述內容確實沒有任何意義。否則,無論如何,所有工作都會在下一次UI刷新前完成,因此您的進度條不會提供任何值(當循環完成時,它只會從0到100)。

只是一個例子,可以實現這種事情。

+0

什麼叫你在哪裏有控制私有變量的公共結構?那是封裝嗎? – 2010-09-16 14:36:30

+0

@hi科技信條:你的意思是'進步'?這只是一個.NET屬性,而不是'struct'。是的,這是封裝的一個重要部分,聽起來像是這個答案很可能對你來說是新的。如果您遇到問題或感到困惑,請告訴我,我會盡我所能提供幫助。 – 2010-09-16 14:40:31

+0

好,所以我的主線程將運行UI,並且我使用後臺工作人員來調用我的控制器方法,然後調用自定義類中的方法與循環。 我是否需要在UI類中運行循環以反覆調用backgroundWorker.ReportProgress?還是自動更新? 謝謝你的耐心答覆,我從來沒有做過線程之前。 – 2010-09-16 14:43:05

1

我通常有一個類在UI上進行調用檢查。 UI - >「UpdaterClass」 - >其他類。

Updater類具有預定義的方法和對UI控件的引用。所以Updater.StepProgressBar()就是我所說的步進UI進度條。我將Updater類引用傳遞給任何需要直接更新UI的類。

這樣,來自不同線程的所有UI更新都由一個類來處理。不是最通用的方式來實現它,但它永遠不會失敗。

實施例僞碼:

class Updater() 
{ 

    public ProgressBar pb; 

    delegate void UpdateProgressBar(); 

    public StepProgressBar() 
    { 
    if(pb.InvokeRequired) 
    { 
      BeginInvoke(new UpdateProgressBar(this.StepProgressBar); 
    } 
    else 
    { 
      pb.Step(); 
     } 
    } 

} 

類似的東西。

+0

這對我來說並不實際,因爲我有許多訪問多個UI的控制器類,每個控制器下面有多個庫。 – 2010-09-16 14:46:58

1

您可以使用委託。當後臺進程創建自定義類時,綁定從自定義類調用的委託來報告更新。然後,您可以在UI層對該呼叫作出反應,並從那裏更新進度欄。

例如(警告,僞代碼):

MyCustomClass class = new MyCustomClass(); 
class.ProgressUpdated += (s,e)=>{ /* update UI */}; 
class.StartLoop(); 
+0

對不起以前從未使用過代表,我必須先閱讀他們。 – 2010-09-16 14:45:13

+0

委託,事件和線程有什麼區別? – 2010-09-16 14:54:04

+0

@丹濤給出了一個很好的例子來說明如何做到這一點。我建議你在嘗試做這件事之前做一些外部事件和代表的閱讀。後臺處理有其自己的缺陷,在進入任何過於複雜的事情之前需要知道如何避免。 – Robaticus 2010-09-16 15:03:29

相關問題