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 に答える