[英]Accessing a Progress bar from (System.Timer)Timer Event gives "Cross-Thread Operation Not Valid)
我正在設計一種表格,其中必須在同時執行一個操作的同時增加進度條(換句話說,我正在顯示此操作的進度)。 此操作需要50秒鍾。 因此,我使用了System.Timer
來增加進度欄。
我的代碼中沒有一個線程。 當我在計時器事件處理程序中編寫Progress_bar.PerformStep()
時,它給出錯誤為“跨線程操作無效”。
[根據該錯誤,我分析了System.Timer
必須正在創建線程並在其中運行計時器以執行多個任務的情況。]
我應該怎么做才能每秒增加進度欄?
我試過這個問題給出的解決方案。 它消除了錯誤,但是現在我看不到進度欄增加了。 意味着它開始了。。。50秒內沒有增加,之后增加100%。
代碼如下:
計時器聲明(它是全局的):
public System.Timers.Timer Thetimer = new System.Timers.Timer(1000);
事件聲明(在構造函數中使用它來聲明...錯誤...公開[可能不是正確的詞]):
Thetimer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
呼叫:
Thetimer.Start();
blRetVal = FunctionToBeExecuted(parameter);
Thetimer.Stop();
事件處理程序:
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//StatusBar.PerformStep(); -- Tried This. It gives the Error
/* This doesn't give an error but Another issue Arises */
if (InvokeRequired)
{
BeginInvoke(new Action(StatusBar.PerformStep));
}
else
StatusBar.PerformStep();
}
PS我正在使用C#和Visual Studio 2008
初始化用於Windows窗體的Timers.Timer對象時,必須將計時器實例的SynchronizingObject屬性設置為窗體。
systemTimersTimerInstance.SynchronizingObject = this; //此=表單實例。
http://msdn.microsoft.com/zh-CN/magazine/cc164015.aspx
魯迪= 8 ^ D
聽起來您正在主線程上執行“后台”操作,這就是為什么進度條在調用時不會更新的原因。
看看BackgroundWorker 。
好。 喬恩B是對的。 您必須將長時間運行的任務放在一個線程中,無法解決。 簡化后,您正在執行以下操作:
public partial class Form1 : Form
{
// ...
public System.Timers.Timer timer = new System.Timers.Timer(1000);
private void Form1_Load(object sender, EventArgs e)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_elapsed);
timer.Start();
// Simulates your long running task (FunctionToBeExecuted)
// NOTE: This freezes the main UI thread for 10 seconds,
// so nothing will be drawn *at all*
Thread.Sleep(10000);
timer.Stop();
}
void timer_elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (InvokeRequired)
this.BeginInvoke(new Action(progressBar1.PerformStep));
else
progressBar1.PerformStep();
}
}
如在Load事件中看到的那樣,您不僅要暫停進度條,而且要暫停主UI線程。 這對於大多數用戶來說是不可接受的,所有優秀的開發人員都應在其工具集中擁有另一個選擇。
解決此問題的唯一方法(運行另一個進程除外)是在另一個線程中運行任務。 最簡單的方法之一是使用BackgroundWorker,這真的很容易。 這是您需要的更改:
public partial class Form1 : Form
{
// ...
private void Form1_Load(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Your work is completed, not needed but can be handy
// e.g. to report in some way that the work is done:
progressBar1.Value = progressBar1.Maximum;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_elapsed);
timer.Start();
// Simulates your long running task (FunctionToBeExecuted)
// Your main UI thread is free!
Thread.Sleep(10000);
timer.Stop();
}
// ...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.