【问题标题】:Why main thread gets hanged when background worker is executing为什么后台工作者正在执行时主线程被挂起
【发布时间】:2013-10-25 11:29:29
【问题描述】:

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

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

【问题讨论】:

  • 你怎么知道主线程挂了?

标签: c# winforms backgroundworker


【解决方案1】:

因为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
    }
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多