none
WinForm - implement worker thread just like BackgroundWorker but get the error RRS feed

  • 问题

  • // sample 1 use BackgroundWorker, it works fine private BackgroundWorker workerPorcee = new BackgroundWorker(); private void button1_Click(object sender, EventArgs e) { workerPorcee.DoWork += new DoWorkEventHandler(workerPorcee_DoWork); workerPorcee.ProgressChanged += new ProgressChangedEventHandler(workerPorcee_ProgressChanged); workerPorcee.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerPorcee_RunWorkerCompleted); workerPorcee.WorkerReportsProgress = true; workerPorcee.RunWorkerAsync(); } void workerPorcee_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.progressBar1.Value = e.ProgressPercentage; } void workerPorcee_DoWork(object sender, DoWorkEventArgs e) { for (int i = 0; i < 100; i++) { workerPorcee.ReportProgress(i); Thread.Sleep(100); } } void workerPorcee_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { this.progressBar1.Value = 100; }

    I just implement my worker thread, but it will get the exception: Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on.

    // my worker thread private void button3_Click(object sender, EventArgs e) { Worker wk = new Worker(); Thread thr = new Thread(new ThreadStart(wk.ProcessEvent)); wk.ProgressChanged += new delCallback(wk_ProgressChanged); thr.Start(); } void wk_ProgressChanged(int percent) { this.progressBar1.Value = percent; //exception:Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on.

    } public delegate void delCallback(int percent); public class Worker { public event delCallback ProgressChanged; public void ProcessEvent() { for (int i = 0; i < 100; i++) { if (ProgressChanged != null) { this.ProgressChanged(i); } Thread.Sleep(100); } } }

    WinForm, I just want to use my worker thread to set the progress bar value, but it fail. Any one help to point what is the issue?

    Miao


    2012年6月28日 9:51

答案

  • In worker thread, call the Invoke of form which is in the UI thread, like below:

     public delegate void delCallback(int percent);
    
        public class Worker
        {
            public event delCallback ProgressChanged;
    
            public void ProcessEvent()
            {
                for (int i = 0; i < 100; i++)
                {
                    if (ProgressChanged != null && ProgressChanged.Target!=null)
                    {
                        ProgressChanged.Target.GetType().InvokeMember("Invoke", BindingFlags.InvokeMethod, null, ProgressChanged.Target, new object[] { ProgressChanged,i });                    
                    }
                    Thread.Sleep(100);
                }
            }
        }

    Using Invoke or BeginInvoke, there is one risk, before the invoke the form or control is disposed, then we will get error. So the best way is to use BackgroundWorker


    Miao

    • 已标记为答案 HaiHua Miao 2012年6月28日 23:12
    2012年6月28日 23:12