1

我有简单的 winforms 应用程序,其中有按钮。点击按钮我正在做这样的事情

    private void Button1_Click(object sender, EventArgs e)
    {
        BackgroundWorker bw_Convert = new BackgroundWorker();
        bw_Convert.WorkerReportsProgress = true;
        bw_Convert.DoWork += bw_Convert_DoWork;
        bw_Convert.RunWorkerCompleted += bw_Convert_RunWorkerCompleted;
        bw_Convert.ProgressChanged += bw_Convert_ProgressChanged;
        bw_Convert.WorkerReportsProgress = true;
        bw_Convert.RunWorkerAsync();
    }

我有以下后台工作人员代码

   public void bw_Convert_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i <= 1000000; i++)
        {                
            bw_Convert.ReportProgress((100 * (i) / 1000));
        }
    }
    public void bw_Convert_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {           

        progressBarControl1.EditValue = e.ProgressPercentage.ToString();
    }

通过做这个。为什么我的主线程在处理后台工作人员中的事情时被挂起。

4

2 回答 2

2

因为ReportProgress事件处理程序是在主线程上执行的:

对 ReportProgress 方法的调用是异步的并立即返回。ProgressChanged 事件处理程序在创建 BackgroundWorker 的线程上执行。

因此,您不断地ReportProgress从后台线程调用,这使您的主线程不断忙于处理此事件。

如果您在后台有很多快速工作要做,请尝试仅报告每个第 n 次迭代,而不是在每次迭代时引发事件:

public void bw_Convert_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i <= 1000000; i++)
    {   
        if (i % 10000 == 0)
           bw_Convert.ReportProgress(i);
        // do something
    }
}
于 2013-10-25T11:30:47.583 回答
1

ProgressChanged事件在 UI 线程上执行,因此您可以访问控件。
后台工作程序中的代码在很短的时间内执行,导致在很短的时间内引发许多事件,使代码做出反应,就好像它会在 UI 线程上完全执行一样。

事实上,大部分工作都是在 UI 线程中完成的,因为更新屏幕上的控件比循环迭代要多得多。

于 2013-10-25T11:31:20.617 回答