为什么主线程在后台工作程序执行时被挂起

时间:2013-10-25 11:29:29

标签: c# winforms backgroundworker

我有简单的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();
    }

通过这样做。为什么我的主线程在我处理Background Worker中的东西时被绞死。

2 个答案:

答案 0 :(得分: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
    }
}

答案 1 :(得分:1)

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

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