0

バックグラウンドワーカーが実際にどのように機能するかについて質問があります。さまざまな方法でどのように機能するかはよくわかりません。

たとえば、次のコードがあります (説明のためにhttp://broadcast.oreilly.com/2010/06/understanding-c-using-backgrou.htmlから適応):

private void getDateTime()
{
    DateTime startTime = DateTime.Now;
    double value = Math.E;
    while (DateTime.Now < startTime.AddMilliseconds(100)) 
    {
      value /= Math.PI;
      value *= Math.Sqrt(2);
    }
}

private backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for(int i=0; i <= 100; i++)
    {
        getDateTime();
        backgroundWorker1.ReportProgress(i);
    }
}

これにより、backgroundworker スレッドを使用して DateTime が継続的に計算されます。ここで、バックグラウンド ワーカーの DoWork メソッド内の for ループが計算を実行し、進行状況を報告し、ループを繰り返すと想定しています (誤解していた場合は訂正してください)。

(おそらく大きな)DataTableを解析して別のDataTableを返す別のメソッドがあると仮定すると、バックグラウンドワーカーでそれを使用すると、DataTableを何度も解析することになります(理論的には、間違っている場合は修正してください) ? これがプログラムの流れである場合、ループを繰り返すことなく DataTable の解析を達成するためのより効率的な方法はありますか?

これは Windows フォームを対象としており、DataTable を解析すると UI がフリーズする傾向があります。backgroundworker が UI のフリーズを回避するのに役立つと聞いたことがありますが、DataTable 全体を何度も再解析しなければならないのは非常に非効率的です。ただし、for ループなしで進行状況を報告できる他の方法もわかりません。

編集:

私は一時的な解決策を見つけました。動作しますが、進捗状況を報告する方法がまだありません。

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        int rows = (int)e.Argument;
        int count = 0;
        t3 = runComparison();
        for (int i = 0; i <= rows; i++)
        {
            count++;
            int current = count / rows;
            backgroundWorker1.ReportProgress(current * 100);
        }
        e.Result = t3;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            MessageBox.Show("An unexpected error has occurred. Please try again later.", "ERROR!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            dataGridView1.DataSource = e.Result;
        }
    }

for ループが何もしないことはわかっています。ただし、「runComparison」はすでに多くの時間を消費しています。そのため、for ループ内にある場合、進行状況は実行全体が報告されるまで報告されません。または、プログレス バーの代わりにラベルまたはメッセージ ボックスを使用することもできます。どうすればこれを達成できるのかよくわかりません。

4

2 に答える 2

1

私はかなりエレガントでない解決策を思いついた。しかし、それは使いやすさの要件を満たしているので...うまくいくものは何でも:P

すべてのフィードバックに感謝します。

とにかく、ここにコードがあります:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        backgroundWorker1.ReportProgress(1); //to invoke ProgressChanged
        t3 = runComparison(); //run intensive method
        e.Result = t3; //return DataTable
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Visible = true; //display a label
        textBoxProgress.Visible = true; //display the progress bar
        //change the progress bar style
        //the Marquee style is constantly running, so it could show users the process is working
        //not too sure how to explain it, you'll have to try it out. 
        progressBar1.Style = ProgressBarStyle.Marquee; 
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            MessageBox.Show("An unexpected error has occurred. Please try again later.", "ERROR!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            //reset the display and update the DataGridView
            progressBar1.Visible = false;
            textBoxProgress.Visible = false;
            progressBar1.Style = ProgressBarStyle.Blocks;
            dataGridView1.DataSource = e.Result;
        }
    }
于 2012-10-16T09:03:15.607 に答える
1

これを試してください:

//make sure background worker report progress
backgroundWorker1.WorkerReportsProgress = True;


private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
    progressBar1.Refresh;
    //if your progressbar is on a status strip, you need to refresh the status strip instead
}
于 2012-10-16T08:06:11.590 に答える