在C#,windows窗體中創建.net應用程序。如何在100循環循環的每個循環中更新進度條1步? (我正在處理循環中的Excel工作表。) 進度條控件位於UI類中,它連接到連接到自定義類 (MVC模式)的控制器類。循環在自定義類中。 我是否需要在每種方法中一直髮送UI類實例還是有更好的方法?如何在每個循環週期內一步更新進度條? C#
當前進度條在循環結束後更新。 Application.doevents和.update或.refresh不起作用。
在C#,windows窗體中創建.net應用程序。如何在100循環循環的每個循環中更新進度條1步? (我正在處理循環中的Excel工作表。) 進度條控件位於UI類中,它連接到連接到自定義類 (MVC模式)的控制器類。循環在自定義類中。 我是否需要在每種方法中一直髮送UI類實例還是有更好的方法?如何在每個循環週期內一步更新進度條? C#
當前進度條在循環結束後更新。 Application.doevents和.update或.refresh不起作用。
說下面是你的類負責做循環工作。添加一個事件來指示你的進度。然後從你的用戶界面簡單地處理該事件並相應地更新進度條。
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)。
只是一個例子,可以實現這種事情。
什麼叫你在哪裏有控制私有變量的公共結構?那是封裝嗎? – 2010-09-16 14:36:30
@hi科技信條:你的意思是'進步'?這只是一個.NET屬性,而不是'struct'。是的,這是封裝的一個重要部分,聽起來像是這個答案很可能對你來說是新的。如果您遇到問題或感到困惑,請告訴我,我會盡我所能提供幫助。 – 2010-09-16 14:40:31
好,所以我的主線程將運行UI,並且我使用後臺工作人員來調用我的控制器方法,然後調用自定義類中的方法與循環。 我是否需要在UI類中運行循環以反覆調用backgroundWorker.ReportProgress?還是自動更新? 謝謝你的耐心答覆,我從來沒有做過線程之前。 – 2010-09-16 14:43:05
我通常有一個類在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();
}
}
}
類似的東西。
這對我來說並不實際,因爲我有許多訪問多個UI的控制器類,每個控制器下面有多個庫。 – 2010-09-16 14:46:58
您可以使用委託。當後臺進程創建自定義類時,綁定從自定義類調用的委託來報告更新。然後,您可以在UI層對該呼叫作出反應,並從那裏更新進度欄。
例如(警告,僞代碼):
MyCustomClass class = new MyCustomClass();
class.ProgressUpdated += (s,e)=>{ /* update UI */};
class.StartLoop();
對不起以前從未使用過代表,我必須先閱讀他們。 – 2010-09-16 14:45:13
委託,事件和線程有什麼區別? – 2010-09-16 14:54:04
@丹濤給出了一個很好的例子來說明如何做到這一點。我建議你在嘗試做這件事之前做一些外部事件和代表的閱讀。後臺處理有其自己的缺陷,在進入任何過於複雜的事情之前需要知道如何避免。 – Robaticus 2010-09-16 15:03:29
在較低級別的活動發佈廣告進展情況時出現了什麼問題? – Joey 2010-09-16 13:38:58
對不起,我不明白你剛剛說的。進度條被定義在一個更高的類中,如果我更新低級類的值,上層類將如何知道?我不得不將ui類實例或進度條實例傳遞到較低級別。 – 2010-09-16 13:45:46
我不確定,但如果更新發生延遲,它幾乎聽起來像是一個線程問題。你在使用invoke嗎(如果有必要)? – 2010-09-16 13:49:19