3

計算の進行状況を報告するバックグラウンド ワーカーがいます。ProgressChangedEventArgs で処理している現在の行番号を返します。そこから、実行することで完了したパーセンテージを判断できます

(int) (100 * (double)e.ProgressPercentage / csTextLines) 

ここで、csTextLines は処理中の行数です。私が遭遇している問題は、合計推定時間と合計残り時間も取得したいということです。私が見たバックグラウンドワーカーには何もないので、DateTimeの計算で行う必要があると思います。TotalEstTime と TimeLeft を取得するためにこれまでに行ったことは次のとおりです。

  • TimeLeft = TotalEstTime - TimeSoFar;
  • TotalEstTime = AvgTimeForEachLine * #OfLines;

どこ

  • TimeSoFar = DateTime.Now - m_startTime;
  • AvgTimeForEachLine = (TimeFromLastLine + TotalTimeForAllLines) / #OfLines;

どこ

  • TimeFromLastLine = DateTime.Now - LastRecordedTime;
  • TotalTimeForAllLines += TimeFromLastLine;

これをコードにすると、これまでのところ

// This event handler updates the progress. 
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        TimeSpan difInCalls = DateTime.Now.Subtract(m_LastProgressCall);
        m_LastProgressCall = DateTime.Now;
        m_totalDif = m_totalDif.Add(difInCalls);
        TimeSpan avgDif = new TimeSpan(0, 0, 0, 0, ((int)m_totalDif.TotalMilliseconds / m_csNumLines));
        double totalTime = m_csNumLines * avgDif.TotalSeconds;
        double timeLeft = totalTime - (DateTime.Now.Subtract(m_Form2Start).TotalSeconds);
        Console.WriteLine("TotalEstTime: " + totalTime + " TimeLeft: " + timeLeft);


        // Update the progress label
        resultLabel.Text = "Line " + e.ProgressPercentage.ToString() + " of " + m_csNumLines + " at " + (int)(100 * (double)e.ProgressPercentage / m_csNumLines) + "% loaded";
    }

私が抱えている問題は、処理される行数に応じて TotalTime が大幅に増加することです。1437 行の文字列では、最初は 1.4 秒あり、最後に残り 18.6 秒と見積もられます。実際には完了するのに16.54秒かかります。

私の2番目の問題は、残り時間が実際には変わらないことです。約1.1から2.5の間で変動します。

何に起因する可能性がありますか?何が問題なのですか?

完全なコードは次のとおりです: http://pastebin.com/x1CCceY7

4

1 に答える 1

5

問題は、最後の進行時間から作業していることです。これは、進行するにつれて変動する可能性があります。開始時間と現在の時間から作業し、完了率を使用すると、作業を進めるにつれて時間が「自己調整」することがわかります。

たとえばDateTime.Now、変数に格納する場合 (m_operationStart名前を付けて など)、次のように記述できます。

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
  if (e.ProgressPercentage != 0)
  {
    double percentageComplete = (double)e.ProgressPercentage / m_csNumLines;

    TimeSpan timeSinceStart = DateTime.Now.Subtract(m_operationStart);
    TimeSpan totalTime = TimeSpan.FromMilliseconds(timeSinceStart.TotalMilliseconds / percentageComplete);
    TimeSpan timeLeft = totalTime - timeSinceStart;

    Console.WriteLine("TotalEstTime: " + totalTime + " TimeLeft: " + timeLeft);


    // Update the progress label
    resultLabel.Text = "Line " + e.ProgressPercentage.ToString() + " of " + m_csNumLines + " at " + (int)(100.0 * percentageComplete) + "% loaded";
  }
  else
    resultLabel.Text = "Line " + e.ProgressPercentage.ToString() + " of " + m_csNumLines;
}
于 2012-08-20T16:23:44.723 に答える