0
    // 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;
    }

我只是实现了我的工作线程,但它会出现异常:跨线程操作无效:控件'progressBar1'从创建它的线程以外的线程访问。

    // 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,我只想使用我的工作线程来设置进度条值,但它失败了。任何人帮助指出什么问题?如何实现与 BackgroundWorker 一样的功能?

4

1 回答 1

0

您需要确保与 winForms 控件的所有交互都在创建控件的主线程上执行 - 这就是异常告诉您的内容。为此,您需要使用 Control.Invoke 方法,该方法将确保在正确的线程上执行对 UI 更改方法的调用。

因此,在您的代码示例中,您需要将其更改为:

void wk_ProgressChanged(int percent)
{
    if(this.progressBar1.InvokeRequired)
    {
        this.progressBar1.Invoke(wk_ProgressChanged, new Object[] {percent});
    }
    else
    {
        this.progressBar1.Value = percent;
    }       
 }

第一部分检查是否正在为 progressBar1 控件正确的线程上执行方法调用。如果我们在不同的线程上,Invoke 用于调用相同的方法,但在正确的线程上。然后 Invoke 将调用 wk_ProgressChanged 方法,但这次 InvokeRequired 将为 false(因为我们现在在正确的线程上运行以执行 UI 更新),并且设置了 progressBar1 值。

于 2012-06-28T22:18:07.347 回答