首页 > 解决方案 > 计算循环中剩余的估计时间(当迭代次数非常大并且每次迭代所需的时间非常低时)

问题描述

我正在尝试计算 for 循环的总剩余时间。总迭代次数可以超过~1010000000。完成“在这里完成的真正工作”所需的总时间远低于一秒,而且变化不大。当我使用我当前的解决方案时,剩余时间会长时间增加,然后开始减少。

我正在寻找更好的解决方案。我能做些什么?

long totalTiles = ((((rightBottom.X) - (topLeft.X)) + 1) * (((rightBottom.Y) - (topLeft.Y)) + 1));
long currentTileProccessed = 0;

DateTime startTime = DateTime.Now;

for (long x = (topLeft.X); x <= (rightBottom.X); x++)
{
    for (long y = (topLeft.Y); y <= (rightBottom.Y); y++)
    {
        **//Real job done here//**

        TimeSpan timeRemaining = TimeSpan.FromTicks(DateTime.Now.Subtract(startTime).Ticks * (totalTiles - (currentTileProccessed + 1)) / (currentTileProccessed + 1));

        this.Dispatcher.Invoke((Action)delegate () {
            EstimatedTimeLeft_TextBlock.Text = "Days : " + timeRemaining.Days.ToString("D2") + ", Hours : " + timeRemaining.Hours.ToString("D2") + ", Minutes :" + timeRemaining.Minutes.ToString("D2") + ", Seconds :" + timeRemaining.Seconds.ToString("D2");
        });

        currentTileProccessed++;
    }
}

标签: c#time

解决方案


在这里,我使用 System.Diagnostics 中的 Stopwatch 来确定最后 100 个任务的平均时间,我将其乘以预期的任务总数减去已经运行的任务数。

注意:剩余时间仍然会增加,如果突然最后 100 个任务开始运行比之前的 10k 慢,这将重新调整您的剩余时间以匹配最近的运行。

long totalTiles = ((((rightBottom.X) - (topLeft.X)) + 1) * (((rightBottom.Y) - (topLeft.Y)) + 1));
long currentTileProccessed = 0;

Queue<long> taskTimes = new Queue<long>();
int taskTimeHistoryLimit = 100;

long taskTotal = (rightBottom.X - topLeft.X) * (rightBottom.Y - topLeft.Y);

Stopwatch watch = new Stopwatch();


long index = 0;
for (long x = (topLeft.X); x <= (rightBottom.X); x++)
{
    for (long y = (topLeft.Y); y <= (rightBottom.Y); y++)
    {
        index++;
        watch.Start();
        //Real job done here//
        watch.Stop();
        taskTimes.Enqueue(watch.ElapsedTicks);
        watch.Reset();
        while (taskTimes.Count > taskTimeHistoryLimit)
        {
            taskTimes.Dequeue();
        }
        TimeSpan timeRemaining = new TimeSpan((taskTotal - index) * (long)taskTimes.Average());

        this.Dispatcher.Invoke((Action)delegate () {
            EstimatedTimeLeft_TextBlock.Text = "Days : " + timeRemaining.Days.ToString("D2") + ", Hours : " + timeRemaining.Hours.ToString("D2") + ", Minutes :" + timeRemaining.Minutes.ToString("D2") + ", Seconds :" + timeRemaining.Seconds.ToString("D2");
        });
    }
}

推荐阅读