计算后台工作人员OnProgressChanged事件的剩余总时间和总时间

时间:2012-08-20 16:14:41

标签: c# winforms datetime date-arithmetic

我有一个后台工作人员报告计算的进度。它返回它在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.4s,最后它估计还有18.6s。实际上需要16.54才能完成。

我的第二个问题是剩下的时间并没有真正改变。它在大约1.1和2.5之间波动。

有什么可归因于?可能是什么问题?

以下是完整代码:http://pastebin.com/x1CCceY7

1 个答案:

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