簡體   English   中英

從(System.Timer)Timer事件訪問進度欄會顯示“跨線程操作無效”

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM