将ETA添加到嵌入式循环序列

如何解决将ETA添加到嵌入式循环序列

更新1:

下面提供的一些解决方案似乎不错。但是,我只知道确定父循环的迭代之后,循环将迭代的次数。因此,我无法预先计算所有迭代次数。

原始问题:

我在类似于以下的程序中嵌入了循环:

Prog1:

using System;
using System.Threading;

namespace time_remaining_loop_strip
{
    class Program
    {
        static void Main(string[] args)
        {
            var random = new Random();
            Console.Clear();

            // Simulate initiation delay
            Console.WriteLine("initiate");
            Thread.Sleep(random.Next(100,1000));

            int intCount = random.Next(1,10);

            for (int loop1 = 0; loop1 <= intCount; loop1++) 
            {
                // Simulate loop1 delay
                Console.WriteLine("\tloop1");
                Thread.Sleep(random.Next(100,1000));

                for (int loop2 = 0; loop2 <= random.Next(1,10); loop2++) 
                {
                    // Simulate loop2 delay
                    Console.WriteLine("\t\tloop2");
                    Thread.Sleep(random.Next(100,1000));

                    for (int loop3 = 0; loop3 <= random.Next(1,10); loop3++) 
                    {
                        // Simulate loop3 delay
                        Console.WriteLine("\t\t\tloop3");
                        Thread.Sleep(random.Next(100,1000));

                        for (int loop4 = 0; loop4 <= random.Next(1,10); loop4++) 
                        {
                            // Simulate loop4 delay
                            Console.WriteLine("\t\t\t\tloop4");
                            Thread.Sleep(random.Next(100,1000));
                        }
                    }
                }
            }
        }
    }
}

我正在尝试显示“剩余处理时间(ETA)”,因此我可以粗略估算出上述循环序列完成之前剩余的时间量

我现在还有另一段代码,它确实显示了一个ETA,当循环非常简单时,它可以正常工作:

Prog2:

using System;
using System.Threading;

namespace time_remaining
{
    class Program
    {
        public static TimeSpan ComputeRemaining((int count,DateTime time) start,(int count,DateTime time) current,int end) =>
            current.count - start.count == 0
            ? TimeSpan.MaxValue
            : TimeSpan.FromSeconds((end - current.count) * current.time.Subtract(start.time).TotalSeconds / (current.count - start.count));

        static void Main(string[] args)
        {
            Console.Clear();

            var random = new Random();
            int Count = random.Next(10,60);
            DateTime startTime = DateTime.Now;

            for (int i = 0; i <= Count; i++)
            {
                Thread.Sleep(random.Next(100,2000));
                TimeSpan timeRemaining = ComputeRemaining((0,startTime),(i,DateTime.Now),Count);

                Console.SetCursorPosition(0,0);
                Console.Write("ETA: ");
                Console.Write(String.Format("{0} Days,{1} Hours,{2} Minutes,{3} Seconds",timeRemaining.Days.ToString().PadLeft(3,'0'),timeRemaining.Hours.ToString().PadLeft(2,timeRemaining.Minutes.ToString().PadLeft(2,timeRemaining.Seconds.ToString().PadLeft(2,'0')));
            }
        }
    }
}

当我尝试将Prog1的ETA方面结合到Prog2中时,它似乎不能很好地工作:

Prog3 = Prog1 + Prog2:

using System;
using System.Threading;

namespace time_remaining_loop_strip
{
    class Program
    {
        public static TimeSpan ComputeRemaining((int count,int end) =>
            current.count - start.count == 0
            ? TimeSpan.MaxValue
            : TimeSpan.FromSeconds((end - current.count) * current.time.Subtract(start.time).TotalSeconds / (current.count - start.count));

        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;
            
            var random = new Random();
            Console.Clear();

            // Simulate initiation delay
            //Console.WriteLine("initiate");
            Thread.Sleep(random.Next(100,10);

            for (int loop1 = 0; loop1 <= intCount; loop1++) 
            {
                // Simulate loop1 delay
                //Console.WriteLine("\tloop1");
                Thread.Sleep(random.Next(100,10); loop2++) 
                {
                    // Simulate loop2 delay
                    //Console.WriteLine("\t\tloop2");
                    Thread.Sleep(random.Next(100,10); loop3++) 
                    {
                        // Simulate loop3 delay
                        //Console.WriteLine("\t\t\tloop3");
                        Thread.Sleep(random.Next(100,10); loop4++) 
                        {
                            // Simulate loop4 delay
                            //Console.WriteLine("\t\t\t\tloop4");
                            Thread.Sleep(random.Next(100,1000));
                        }
                    }
                }

                TimeSpan timeRemaining = ComputeRemaining((0,(loop1,intCount);

                Console.SetCursorPosition(0,'0')));
            }
        }
    }
}

这似乎一点也不奏效。它确实显示了ETA,但是由于循环的结构方式,它在显示任何内容之前都有很长的延迟。

如何更新此信息,以便ETA代码更准确,更可预测的间隔(如每秒)显示ETA?

解决方法

基于这样的假设,您已经建立了一个简单的实际发生情况的模型(您有一系列嵌套的变量延迟和计数过程,甚至在运行时都无法确定),因此当前需要的是随机数预测子。

nm持续时间(100和1000ms)之间将有op个周期(在您的示例中为1和10),但仍然是随机的好吧,随机量化为频段。您编写的方式是骰子随机的(骰子没有记忆),尽管在实践中,一个周期的持续时间似乎更有可能暗示着下一个周期的持续时间(这就是您的做法) ComputeRemaining),并且在一个频段内,一个循环的计数必须有助于下一循环的计数。

因此,尽管Prog2看起来很简单,但仍涵盖了我们的示例..给定一个已知的循环计数,其中每个周期需要一个随机的持续时间(实际上是pick(n,m)^3*pick(o,p) ..但这仍然只是随机的数字)-预测结束。为了报告的目的,您也希望重构它以考虑内部循环,但是实际上是相同的过程。 ( ^ 3是一种简化,实际上是一系列独立的选择权相乘

好吧,所以我们不需要谈论时间/延迟(我的意思是..您显然希望这样做,但这只是代表未来的某个数字-TimeSpanlong一段时间以来x滴答的计数...结束时间仅为Now + x*tick)。因此,我们可以将其简化为long预测变量。

设置

interface IAvger
{
    public double Avg { get; }
}
interface IAdder
{
    void Add(long value);
}
class Mean
{
    private int _count = 0;

    public double Total { get; private set; } = 0;
    public double? Avg => _count == 0 ? null : (double?)(Total / _count);

    public void Add(double val)
    {
        Total += val;
        _count++;
    }
}

您可以忽略接口(我在切换潜在解决方案时使用了它们)。类Mean应该很熟悉...它计算多个值的平均平均值,并在找到更多值时进行缩放/调整。

/// <summary>
/// Equivalent to your ComputeRemaining
/// </summary>
class RunningAvg : IAvger,IAdder
{
    private Mean _mean = new Mean();
    private readonly double _guess;
    public RunningAvg(double guess)
    {
        _guess = guess;
    }

    public double Avg => _mean.Avg ?? _guess;

    public void Add(long value) => _mean.Add(value);
}

这里等同于您的ComputeRemainingguess的值有助于在其他情况一无所知的情况下进行早期预测(与TimeSpan.Max等效)

/// <summary>
/// Drop the lowest and highest value
/// - Fairly typical in stats,however note this is only one biggest/smallest
/// (will work best when the standard devation is low,and outliers
/// are rare)
/// </summary>
class IgnoreExtremes : IAvger,IAdder
{
    private long? _worst;
    private long? _best;
    private Mean _mean = new Mean();
    private readonly int _wt;
    private readonly double _guess;
    public IgnoreExtremes(double guess,int weight = 4)
    {
        _wt = weight;
        _guess = guess;
    }

    public long Best => _best ?? (long)Math.Round(_guess);
    public long Worst => _worst ?? (long)Math.Round(_guess);

    public double Avg
    {
        get
        {
            var avg = _mean.Avg;
            if (!avg.HasValue) return _guess;
            return (Best + _wt * avg.Value + Worst) / (2 + _wt);
        }
    }

    public void Add(long value)
    {
        if (!_best.HasValue)
        {
            _best = value;
        }
        else if (value < _best)
        {
            _mean.Add(_best.Value);
            _best = value;
        }
        else if (!_worst.HasValue)
        {
            _worst = value;
        }
        else if (value > _worst)
        {
            _mean.Add(_worst.Value);
            _worst = value;
        }
        else
        {
            _mean.Add(value);
        }
    }
}

最后一些统计! IgnoreExtremes抑制最高和最低(单个)值。在科学采样中,通常会忽略它们,但是如果使用数字的真实随机分布(例如骰子掷骰或random.Next),则只会丢弃一个极端。这应该比RunningAvg预测更好的数字。请注意,这是加权平均的一种形式,您可以通过在构造时提供weight值(wt=4很普遍)或将_wt与{{1} }(需要更改一些代码)

_mean.count

另一种统计方法是忽略平均值超过class IgnoreStdDevOutlier : IAvger,IAdder { private const int AT_LEAST = 5; private Mean _mean = new Mean(); private readonly List<long> _vals = new List<long>(); private readonly double _guess; //private long _tot; private readonly double _outlierStdDevMulti; public IgnoreStdDevOutlier(double guess,double outlierStdDevMulti = 2) { _guess = guess; _outlierStdDevMulti = outlierStdDevMulti; } private double StdDev() { var avg = Avg; double tot = 0; foreach (var item in _vals) tot += (item - avg) * (item - avg); return Math.Sqrt(tot / (_vals.Count - 1)); } public void Add(long value) { _vals.Add(value); if (_vals.Count > AT_LEAST) { var avg = Avg; var sd = StdDev(); var min = avg - _outlierStdDevMulti * sd; var max = avg + _outlierStdDevMulti * sd; //Ignore outliers if (value < min || value > max) return; } _mean.Add(value); } public double Avg => _mean.Avg ?? 0; } 的值,其中n*StandardDeviation通常为2或3(您会发现意见不一致)。看到的所有值都是标准偏差的一部分,但只有那些不是异常值的值才被视为平均值的一部分。最终像抑制因素一样起作用,防止了估计值的太大波动。

好的,要运行测试,我们需要某种测量类:

n

真实的猜测无法得知最终(class Performance { private readonly List<long> _set = new List<long>(); private long _actual; public void Add(long item) => _set.Add(item); public void SetFinal(long final) => _actual = final; public void Report() { foreach (var item in _set) { Console.WriteLine("{0} {1} = {2}",item,_actual,(item / (double)_actual - 1) * 100); } } } )的值,但是该类使我们可以看到到目前为止的猜测如何。

最后是程序类:

_actual

您可以忽略工作是通过称为class Program { const int MIN_MSEC = 100; const int MAX_MSEC = 1000; const int MIN_LOOP = 10; const int MAX_LOOP = 50; static void C(Random random) { int nm = random.Next(MAX_LOOP,MAX_LOOP); var guess = (double)((MAX_LOOP + MIN_LOOP) / 2 * (MAX_MSEC + MIN_MSEC) / 2); var predict = new RunningAvg(guess); //var predict = new IgnoreExtremes(guess); //var predict = new IgnoreStdDevOutlier(guess,3); var per = new Performance(); long tot = 0; for (int i = 0; i <= nm; i++) { var op = random.Next(MIN_MSEC,MAX_MSEC); predict.Add(op); per.Add((long)Math.Round(predict.Avg * nm)); tot += op; } per.SetFinal(tot); per.Report(); } static void Main(string[] args) { var random = new Random(); C(random); } } 的方法完成的(只是代码的副作用-C是Prog1,而A是Prog2)。在B中,尝试更改CRunningAvgIgnoreExtremes中未注释的内容。同样,因为所写内容是骰子随机的,所以您不能将一次运行作为一个良好的基准。下一阶段是将其包装在重复运行中,并取预测的标准偏差的平均值(或者可能仅取较晚的预测-用户可能不介意,如果早期的估计值相差甚远,最终它没有跳来跳去)-但是我没时间了。我发现IgnoreStdDevOutlier平均会在正确答案上迅速收敛,到最后最终下降了0-1%。 IgnoreStdDevOutlier只能忽略一个极端(在每个方向上),因此有点像IgnoreExtremes。如果您的数据不是随机的,并且偶尔只有极端的情况-那就可以了。 IgnoreStdDevOutlier实际上在某些时候的表现并不理想,而在其他时候则一直以两位数的百分比下降。只要是易于预测的随机数。

使用说明

  • RunningAvg很长。所有这些都是为了预测很长的时间而写的,可以将其视为当时与现在之间的差异。要直接切换,请使用Timespan.Ticks来建立跨度,并使用new Timespan(long ticks)来获得跨度。显然,所有这些类都可以为DateTime.Now.Subtract(startTime).Ticks而不是TimeSpan重写。.不幸的是,没有一个简单的通用long约束同时包含where和{{1 }}
,

您可以知道循环4(L4)将执行L1t L2t L3t * L4t =总数的次数。现在,您一开始就声明

dt = DateTime.Now;
count = 0L;

现在在L4内部,您可以增加计数并计算经过的时间

et= DateTime.Now - dt;
count++;

然后使用3的规则计算出要达到总迭代次数的秒数。

remainingSeconds = (total*et.TotalSeconds/count) - et.TotalSeconds;

现在的预计到达时间是

DateTime.Now.AddSeconds(remainingSeconds);
,

我用下面的逻辑来解决这个问题。

  1. 在每次循环之前,我先计算所有不同的循环计数。

  2. 之后,我创建了4个不同的变量来保存每个循环的睡眠时间,这些循环是其中的设置。

  3. 现在在第一个for循环之前,我使用以下逻辑计算了所有循环将花费的总时间(以毫秒为单位):

    var totalTime =(firstLoopCount * firstLoopSleepTime)+ (firstLoopCount * secondLoopCount * secondLoopSleepTime)+ (firstLoopCount * secondLoopCount * thirdLoopCount * thirdLoopSleepTime)+ (firstLoopCount * secondLoopCount * thirdLoopCount * thirdLoopCount * FourthLoopSleepTime);

注意:我在函数调用(GetTotoalTimeinMilliSecond)中添加了1,其中循环计数通过了,因为循环从0开始并以不同的循环计数(包括其自身)结束。

  1. 现在开始循环,打印已花费的总时间
  2. 在每个循环内,在线程休眠之后,从总时间中减去线程休眠时间并打印出来。并将新的计算时间设置为总时间。
  3. 在每个循环中重复此操作。

下面是代码:

 class Program
 {

    static void Main(string[] args)
    {
        DateTime startTime = DateTime.Now;

        var random = new Random();
        Console.Clear();

        // Simulate initiation delay
        //Console.WriteLine("initiate");
        Thread.Sleep(random.Next(100,1000));

        int firstLoopCount =  random.Next(1,10);
        int secondLoopCount = random.Next(1,10);
        int thirdLoopCount = random.Next(1,10);
        int fourthLoopCount = random.Next(1,10);

        int firstLoopSleepTime = random.Next(100,1000);
        int secondLoopSleepTime =random.Next(100,1000);
        int thirdLoopSleepTime = random.Next(100,1000);
        int fourthLoopSleepTime = random.Next(100,1000);
        //**************Added 1 because loop is starting from 0 and ending with different loops count including itself.
        var totalTimeinMillSec = GetTotoalTimeinMilliSecond(firstLoopCount + 1,secondLoopCount + 1,thirdLoopCount + 1,fourthLoopCount + 1,firstLoopSleepTime,secondLoopSleepTime,thirdLoopSleepTime,fourthLoopSleepTime);

        PrintAndGetTimeRemaining(totalTimeinMillSec);        
        for (int loop1 = 0; loop1 <= firstLoopCount; loop1++)
        {
            // Simulate loop1 delay
            //Console.WriteLine("\tloop1");

            Thread.Sleep(firstLoopSleepTime);
            totalTimeinMillSec = PrintAndGetTimeRemaining(totalTimeinMillSec - firstLoopSleepTime);
            
            for (int loop2 = 0; loop2 <= secondLoopCount; loop2++)
            {
                // Simulate loop2 delay
                //Console.WriteLine("\t\tloop2");
                Thread.Sleep(secondLoopSleepTime);                   
                totalTimeinMillSec = PrintAndGetTimeRemaining(totalTimeinMillSec - secondLoopSleepTime);
                for (int loop3 = 0; loop3 <= thirdLoopCount; loop3++)
                {
                    // Simulate loop3 delay
                    //Console.WriteLine("\t\t\tloop3");
                    Thread.Sleep(thirdLoopSleepTime);                      
                    totalTimeinMillSec = PrintAndGetTimeRemaining(totalTimeinMillSec - thirdLoopSleepTime);
                    for (int loop4 = 0; loop4 <= fourthLoopCount; loop4++)
                    {
                        // Simulate loop4 delay
                        //Console.WriteLine("\t\t\t\tloop4");
                        Thread.Sleep(fourthLoopSleepTime);                           
                        totalTimeinMillSec = PrintAndGetTimeRemaining(totalTimeinMillSec - fourthLoopSleepTime);
                    }
                }
            }
        }
    }

    private static int PrintAndGetTimeRemaining(int totalTimeinMillSec)
    {
        TimeSpan timeRemaining = TimeSpan.FromMilliseconds(totalTimeinMillSec);

        Console.SetCursorPosition(0,0);
        Console.WriteLine("ETA: ");
        Console.WriteLine(String.Format("{0} Days,{1} Hours,{2} Minutes,{3} Seconds,{4} Milliseconds",timeRemaining.Days.ToString().PadLeft(3,'0'),timeRemaining.Hours.ToString().PadLeft(2,timeRemaining.Minutes.ToString().PadLeft(2,timeRemaining.Seconds.ToString().PadLeft(2,timeRemaining.Milliseconds.ToString().PadLeft(2,'0')));
        return totalTimeinMillSec;
    }

    private static int GetTotoalTimeinMilliSecond(int firstLoopCount,int secondLoopCount,int thirdLoopCount,int fourthLoopCount,int firstLoopSleepTime,int secondLoopSleepTime,int thirdLoopSleepTime,int fourthLoopSleepTime)
    {
        var totalTime = (firstLoopCount * firstLoopSleepTime +
                                  firstLoopCount * secondLoopCount * secondLoopSleepTime +
                                  firstLoopCount * secondLoopCount * thirdLoopCount * thirdLoopSleepTime +
                                  firstLoopCount * secondLoopCount * thirdLoopCount * fourthLoopCount * fourthLoopSleepTime);
        
        return totalTime;
    }

}


}

如果我错过了什么,请告诉我。

,

我认为这可能对您有用;为了完成该解决方案,我创建了一些类来提供帮助。

代码本身有一些注释。

首先是一个枚举,要知道我们在哪个循环中;这不是完全必要的,但是稍后值得重构。

public enum LoopEnum
{
    loop1,loop2,loop3,loop4
}

然后我创建了一个名为EtaLoop的类,它将包含整个循环信息/逻辑,以了解循环的一次迭代需要多长时间,我使用StopWatch

public class EtaLoop
{
    public readonly int TotalIterations;
    private readonly List<long> _loopsTimesInMiliseconds;
    private readonly Stopwatch _stopwatch;

    public EtaLoop(int totalIterations)
    {
        //+1 as the loops starts on 0
        TotalIterations = totalIterations+1;
        _loopsTimesInMiliseconds = new List<long>();
        _stopwatch = new Stopwatch();

    }
    public double AvgExecution()
    {
        return _loopsTimesInMiliseconds.Any() ? _loopsTimesInMiliseconds.Average(a => a) : 0;
    }

    public void Start()
    {
        if(!_stopwatch.IsRunning)
            _stopwatch.Start();
    }

    public void Stop()
    {
        _stopwatch.Stop();
        _loopsTimesInMiliseconds.Add(_stopwatch.ElapsedMilliseconds);
        ResetStopWatch();
    }
    public int CurrentIteration()
    {
        return _loopsTimesInMiliseconds.Count();
    }

    public long EstimatedCurrentIteration()
    {
        return Convert.ToInt64(_loopsTimesInMiliseconds.Average(a => a) * TotalIterations);
    }

    private void ResetStopWatch()
    {
        _stopwatch.Reset();
    }
}

我认为这些方法足够清晰,无需更多说明。

另一个名为EtaTime的类将包含更多的逻辑,例如,该类是EtaLoop的包装器,如果a for具有5次迭代,则它将在列表中包含5个元素。

每个元素(EtaLoop)都会添加到列表中,一旦我们完成了(所有迭代都完成了),它就会有更多方法,其中一种是“硬方法”,它会得到解释

public class EtaTime
{
    public readonly List<EtaLoop> Loops;
    public readonly LoopEnum Loop;
    private EtaLoop _currentLoop;

    public EtaTime(LoopEnum loop)
    {
        Loops = new List<EtaLoop>();
        Loop = loop;
    }

    public void SetUpTotal(int totalIterations)
    {
        _currentLoop = new EtaLoop(totalIterations);
    }

    public void StartLoop()
    {
        _currentLoop.Start();

    }

    public void EndLoop()
    {
        _currentLoop.Stop();
    }

    public void RegisterLoop()
    {
        Loops.Add(_currentLoop);
    }

    /// <summary>
    /// Get the average time per execution,and the average number of loops per parent loop.
    /// The idea is to know how many times (and how long) the loop x is executed per each x-1
    /// </summary>
    /// <returns></returns>
    public (double,double) GetAvgTimeAndAvgExTimes()
    {
        double avgTimePerLoop = Loops.Any() ? Loops.Average(a => a.AvgExecution()) : _currentLoop.AvgExecution();
        double avgTotalLoopsIteration = Loops.Any() ? Loops.Average(a => a.TotalIterations) : _currentLoop.TotalIterations;
        return (avgTimePerLoop,avgTotalLoopsIteration);
    }

    public int GetCurrentIteration()
    {
        return _currentLoop.CurrentIteration();
    }

    public int TotalIterations()
    {
        return _currentLoop.TotalIterations;
    }
}

最后,EtaTimeHelper的包装器将包含所有EtaTimes;最初我想列出一个列表,这就是enum为何使用的原因,但是我认为这样更清楚。 注意:此类可以拆分/移动到扩展方法。

这里的要点是RegisterLoop,每次完成循环时,我们都必须调用该方法。它必须在这里,因为我需要其他循环的信息。

public class EtaTimeHelper
{
    //This part can be done in a list,but i think it is easier to see like this.
    public readonly EtaTime Loop1;
    public readonly EtaTime Loop2;
    public readonly EtaTime Loop3;
    public readonly EtaTime Loop4;
    public readonly DateTime StartTime;
    private DateTime _lastPrintTime;
    private const int TimeBetweenPrintsInSeconds = 10;


    public EtaTimeHelper()
    {
        Loop1 = new EtaTime(LoopEnum.loop1);
        Loop2 = new EtaTime(LoopEnum.loop2);
        Loop3 = new EtaTime(LoopEnum.loop3);
        Loop4 = new EtaTime(LoopEnum.loop4);
        StartTime = DateTime.Now;
        _lastPrintTime = DateTime.MinValue;
    }

    public void RegisterLoop(LoopEnum loopNumber)
    {

        switch (loopNumber)
        {
            case LoopEnum.loop1:
                Loop1.RegisterLoop();
                break;
            case LoopEnum.loop2:
                Loop2.RegisterLoop();
                break;
            case LoopEnum.loop3:
                Loop3.RegisterLoop();
                break;
            case LoopEnum.loop4:
                Loop4.RegisterLoop();
                break;
            default:
                throw new NotImplementedException("please register the loop");

        }

        PrintCompletionTime(DateTime.Now,loopNumber);
    }


    public void PrintCompletionTime(DateTime printTime,LoopEnum loopNumber)
    {
        if(_lastPrintTime.AddSeconds(TimeBetweenPrintsInSeconds) < printTime)
        {
            var time = CalculatePredictionTime(loopNumber);
            Print(time);
            _lastPrintTime = printTime;
        }
    }

    private long CalculatePredictionTime(LoopEnum loopNumber)
    {
        switch (loopNumber)
        {
            case LoopEnum.loop1: 
                return LoopPrediction(Loop1.GetAvgTimeAndAvgExTimes());
            case LoopEnum.loop2:
                return Loop2Prediction(Loop1,Loop2);
            case LoopEnum.loop3:
                return Loop3Prediction(Loop1,Loop2,Loop3);
            case LoopEnum.loop4:
                return Loop4Prediction(Loop1,Loop3,Loop4);
            default:
                throw new NotImplementedException("please register the loop");

        }


        //If all loops in #1 are finished,all sub loops are also finished. which means,it is the "end of the loop"
        long LoopPrediction((double,double) avgTimeAndAvgExTimes)
        {
            double avgTimePerLoop = avgTimeAndAvgExTimes.Item1;
            double avgIterations = avgTimeAndAvgExTimes.Item2;
            return Convert.ToInt64(avgTimePerLoop * avgIterations);
        }

        long Loop2Prediction(EtaTime loop1,EtaTime loop2)
        {
            
            var loop1Prediction = LoopPrediction(loop1.GetAvgTimeAndAvgExTimes());

            var loop2Values = loop2.GetAvgTimeAndAvgExTimes();
            long avgPerLoop = LoopPrediction(loop2Values);

            var loop1AvgIterations = loop1.GetAvgTimeAndAvgExTimes().Item2;
            var expectedLoop2Iterations = loop1AvgIterations;

            double loop2Predictions = avgPerLoop * expectedLoop2Iterations;

            if (loop1Prediction == 0)
            {
                return Convert.ToInt64(loop2Predictions);
            }
            else
            {
                //1+current iteration
                return loop1Prediction + loop2.GetCurrentIteration();
            }
        }

        long Loop3Prediction(EtaTime loop1,EtaTime loop2,EtaTime loop3)
        {
            var loop1_2Prediction = Loop2Prediction(loop1,loop2);

            var loop3Values = loop3.GetAvgTimeAndAvgExTimes();
            long avgPerLoop = LoopPrediction(loop3Values);

            var loop2AvgIterations = loop2.GetAvgTimeAndAvgExTimes().Item2;
            var loop1AvgIterations = loop1.GetAvgTimeAndAvgExTimes().Item2;
            var expectedLoop3Iterations = loop2AvgIterations * loop1AvgIterations;

            double loop3Predictions = avgPerLoop * expectedLoop3Iterations;

            if (loop1_2Prediction == 0)
            {
                return Convert.ToInt64(loop3Predictions);
            }
            else
            {
                //1-2+current iteration
                return loop1_2Prediction+ loop3.GetCurrentIteration();
            }
        }

        long Loop4Prediction(EtaTime loop1,EtaTime loop3,EtaTime loop4)
        {
            var loop1_2_3Prediction = Loop3Prediction(loop1,loop3);

            var loop4Values = loop4.GetAvgTimeAndAvgExTimes();
            long avgPerLoop = LoopPrediction(loop4Values);

            var loop2AvgIterations = loop2.GetAvgTimeAndAvgExTimes().Item2;
            var loop1AvgIterations = loop1.GetAvgTimeAndAvgExTimes().Item2;
            var loop3AvgIterations = loop3.GetAvgTimeAndAvgExTimes().Item2;
            var expectedLoop4Iterations = loop2AvgIterations * loop1AvgIterations* loop3AvgIterations;

            double loop4Predictions = avgPerLoop * expectedLoop4Iterations;

            if (loop1_2_3Prediction == 0)
            {
                return Convert.ToInt64(loop4Predictions);
            }
            else
            {
                //1-2-3+current iteration
                return loop1_2_3Prediction + loop4.GetCurrentIteration();
            }
        }
    }

    private void Print(long ms)
    {
        DateTime estimatedCompletionTime = StartTime.AddMilliseconds(ms);

        TimeSpan leftTime = (estimatedCompletionTime - DateTime.Now);

        Console.WriteLine("ETA: ");
        Console.WriteLine($"{leftTime.Days} Days,{leftTime.Hours} Hours,{leftTime.Minutes} Minutes,{leftTime.Seconds} Seconds");//,leftTime.Days.ToString().PadLeft(3,leftTime.Hours.ToString().PadLeft(2,leftTime.Minutes.ToString().PadLeft(2,leftTime.Seconds.ToString().PadLeft(2,'0')));
        Console.WriteLine($"on {estimatedCompletionTime.ToString("yyyy/MM/dd HH:mm:ss")}");
        Console.WriteLine($"Current Time: {DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}");
    }

}

和打印。正如您提到的,您希望打印一些mecanisim,但是您没有指定它是Web的consol应用程序还是winforms应用程序。如果它是桌面应用程序,则可能是winforms,您可能可以执行类似myLabel.SetPropertyThreadSafe的操作来修改要更新的标签。 我计算了CalculatePredictionTime上的时间的算法,我试图将其设为n个循环的单个方法,但是我无法。

现在是主体。

我在Thread.Sleep上做了一些更改,因为在进行测试时,我更容易弄清楚是否有意义。另外,我认为范围是10-100(10x),很大,出于测试原因,我将其减小了。

代码遵循一种模式,首先您需要实例化EtaTimeHelper类。

  • 在每次循环之前,您必须先setUpTotal,这意味着您必须通过迭代次数。
  • 循环的第一行将是.StartLoop(),它将开始StopWatch,循环的最后一行(在}之前)将是.EndLoop()
  • 在右括号}之后,您必须指明etaTimeHelper.RegisterLoop(loopNumber);作为参数传递循环号,该循环号将在必要时打印。
static void Main(string[] args)
{

    var random = new Random();
    Console.Clear();

    // Simulate initiation delay
    //Console.WriteLine("initiate");

    EtaTimeHelper etaTimeHelper = new EtaTimeHelper();


    int intCount = random.Next(1,10);
    etaTimeHelper.Loop1.SetUpTotal(intCount);
    for (int loop1 = 0; loop1 <= intCount; loop1++)
    {
        etaTimeHelper.Loop1.StartLoop();

        // Simulate loop1 delay
        Console.WriteLine("\tloop1");
        Thread.Sleep(random.Next(40,50));

        //number of times the loop 2 is going to execute inside this loop 1;
        int loop2times = random.Next(1,10);
        etaTimeHelper.Loop2.SetUpTotal(loop2times);
        for (int loop2 = 0; loop2 <= loop2times; loop2++)
        {
            etaTimeHelper.Loop2.StartLoop();

            // Simulate loop2 delay
            //Console.WriteLine("\t\tloop2");
            Thread.Sleep(random.Next(30,40));
            
            //number of times the loop 3 is going to execute inside this loop 3;
            int loop3times = random.Next(1,10);
            etaTimeHelper.Loop3.SetUpTotal(loop3times);
            for (int loop3 = 0; loop3 <= loop3times; loop3++)
            {
                etaTimeHelper.Loop3.StartLoop();

                // Simulate loop3 delay
                //Console.WriteLine("\t\t\tloop3");
                Thread.Sleep(random.Next(10,20));


                var loop4Times = random.Next(1,10);
                etaTimeHelper.Loop4.SetUpTotal(loop4Times);
                for (int loop4 = 0; loop4 <= loop4Times; loop4++)
                {
                    etaTimeHelper.Loop4.StartLoop();
                    // Simulate loop4 delay
                    //Console.WriteLine("\t\t\t\tloop4");
                    Thread.Sleep(random.Next(20,30));

                    etaTimeHelper.Loop4.EndLoop();
                }
                etaTimeHelper.RegisterLoop(LoopEnum.loop4);
                etaTimeHelper.Loop3.EndLoop();
            }
            etaTimeHelper.RegisterLoop(LoopEnum.loop3);
            etaTimeHelper.Loop2.EndLoop();
        }
        etaTimeHelper.RegisterLoop(LoopEnum.loop2);
        etaTimeHelper.Loop1.EndLoop();
    }
    etaTimeHelper.RegisterLoop(LoopEnum.loop1);
}

这是一个“工作中的”小提琴https://dotnetfiddle.net/Z06W4g 注意:几秒钟后超时,在您的本地计算机上可以正常工作。

,

为了每秒确定一次ETA,我所做的就是将事件附加到 class HymnRepository(private val hymnDatabaseDao: HymnDatabaseDao) { val allhymns: LiveData<List<Data>> = hymnDatabaseDao.getAllHymns() suspend fun insert(data: Data){ insert(data) } suspend fun getHymnById(hymnId:Int):Data{ return getHymnById(hymnId) } } 对象上。该事件将每秒触发一次,以便不断向用户提供ETA反馈。

System.Timers.Timer

在您的示例中,我们使用 System.Timers.Timer aTimer = new System.Timers.Timer(1000); aTimer.Elapsed += (sender,e) => ATimer_Elapsed(sender,e,new MyEventArguments { Loop1TotalIterations = intCount,CurrentIndex = loop1,Start = startTime }); aTimer.AutoReset = true; aTimer.Enabled = true; 来模拟延迟。

使用Thread.Sleep将使所有内容进入睡眠状态,因此时间逻辑将不准确。

我所做的是创建一个多线程应用程序-为了在一个线程上运行逻辑而在另一个线程上运行时间。因此,当我们暂停时间检查时,ETA将继续运行。

将所有内容放在一起,我们有以下内容:

Thread.Sleep

我在控制台反馈中添加了一些颜色-使更改更加明显。

,

我认为您必须针对所需的操作对其进行几次基准测试,然后进行推断。这里有变量。目标的计算能力和存储类型(如果涉及)和网络(如果涉及)都将对ETA有所贡献,并且每次执行都会有不同的执行时间。但是在进行一些基准测试后,ETA可以被密切预测。而且,如果您想变得真正聪明,则可以显示一条警告,因为x,y和z等原因,它可能比显示的ETA花费更多的时间。目标上运行的其他进程的CPU利用率。

Jon Skeet是这个主题的权威,他在这里拥有丰富的资源: link

也请阅读此处,了解您的操作类型和CPU位数将如何影响您的ETA: link

,

这可能不是理想的解决方案,但有可能解决该问题。
首先,您在Tree中构建一个Action,其中包含要执行的内容,然后通过迭代树来执行Actions
该树充当要执行的内容的索引。即使您可以跟踪正在执行的操作。完成了什么,有什么要完成。

出于演示目的,我已经将动作嵌套在树中的单个级别中,但是您可以在循环等内部尽可能多地嵌套树(前面是伪代码,但poc可以很好地构建和执行)

class Program
{
    static void Main(string[] args)
    {
        var random = new Random();

        TreeNode<Action> root = new TreeNode<Action>(() => { });

        var loop1 = root.AddChild(() =>
        {
            int Count = random.Next(1,3);

            for (int i = 0; i <= Count; i++)
                Thread.Sleep(random.Next(100,2000));
        });

        var loop2 = loop1.AddChild(() =>
        {
            int Count = random.Next(1,2000));
        });

        var loop3 = loop2.AddChild(() =>
        {
            int Count = random.Next(1,2000));
        });

        var loop4 = loop3.AddChild(() =>
        {
            int Count = random.Next(1,2000));
        });

        var loop5 = loop4.AddChild(() =>
        {
            int Count = random.Next(1,2000));
        });

        var loop6 = loop5.AddChild(() =>
        {
            int Count = random.Next(1,2000));
        });

        root.Execute(DateTime.Now);
        Console.ReadLine();
    }
}
public static class Extensions
{
    public static string Humanize(this TimeSpan timeRemaining)
    {
        return String.Format("{0} Days,{3} Seconds",'0'));
    }

    public static void PrintETA(this TimeSpan timeRemaining)
    {
        //Console.SetCursorPosition(0,0);
        Console.Write("ETA: ");
        Console.Write(timeRemaining.Humanize());
    }

    public static TimeSpan ComputeRemaining((int count,DateTime time) start,(int count,DateTime time) current,int end) =>
        current.count - start.count == 0
        ? TimeSpan.MaxValue
        : TimeSpan.FromSeconds((end - current.count) * current.time.Subtract(start.time).TotalSeconds / (current.count - start.count));

    public static void Execute(this TreeNode<Action> root,DateTime startTime)
    {
        var current = root;
        var end = current.Count();
        var currentCount = 1;
    Iterate:
        var Count = current.Children.Count();
        for (int i = 0; i < Count; i++)
        {
            TreeNode<Action> node = current.Children.ElementAt(i);
            node.Data();

            TimeSpan timeRemaining = ComputeRemaining((0,startTime),(currentCount++,DateTime.Now),end-1);
            timeRemaining.PrintETA();
            Console.WriteLine();
            Console.WriteLine("Processed {0} of {1}",currentCount - 1,end-1);

            if (node.Children.Count() > 0)
            {
                current = node;
                goto Iterate;
            }
        }
    }
}

参考: TreeNode.cs

另一个树结构:https://github.com/gt4dev/yet-another-tree-structure

,

已更新。 答案的第一个版本在每次迭代结束时计算RemainingTime和TotalTime的值。给定for循环的嵌套方式,这可能导致更新之间的长时间延迟。为了以给定的时间间隔读取这些值,需要进行一些更改。

让我们从Loop类开始。它用于跟踪每个for循环的详细信息,例如迭代总数,当前迭代以及每次迭代消耗的时间。为了完善后者,使用了两个System.Diagnostic秒表。保持自由运行,而无需复位,以简化迭代平均时间的计算。通过属性获取器访问时,每次迭代都会重置另一个时钟,以提供LoopTime的值,该值可用于RemainingTime和TotalTime的即时计算中。当迭代结束时,通过StopClock()方法发出信号,将更新平均循环时间和相关属性。此处获得的值比即时计算出的值更准确。

它的父类LoopTimer类负责创建和存储Loop实例的引用,启动和停止时钟以及计算全局ETA。在for循环的开始使用EnterLoop()方法。它创建一个新的循环。在其余的迭代中,将使用具有单个参数的重载EnterLoop()来检索存储在Dictionary中的Loop实例。循环结束时,方法ExitLoop()停止时钟并更新计算。

提供函数ExitLoopRetETA()和ExitLoopRetTotalEta()作为ExitLoop()的替代品,以在循环结束时打印数据,以进行测试或调试。方法Bonus()显示了如何使用它。方法ShowStatus()和函数GetStatus提供有关Loop对象的内部信息。

要定期显示这些值,可以使用一个Task来在单独的线程中运行DoUpdate()(或DoUpdateTotal()或DoUpdateStatus())。

目标框架是.Net 4.0

工人阶级:


using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace LoopTimer
{
  public struct TotalEta
  {
      public TimeSpan Eta;
      public TimeSpan Total;
  }

  internal class LoopTimer
  {
      // Private helper class
      private class Loop
      {
          // Declarations
          private Stopwatch _clock;
          private Stopwatch _interval_clock;

          // Constructor
          public Loop(int index,int count)
          {
              Index = index;
              Count = count;

              _clock = new Stopwatch();
              _interval_clock = new Stopwatch();
          }

          // Properties
          internal int Index { get; set; }

          internal int Count { get; private set; }

          private double _loopTimeMs;
          internal double LoopTimeMs
          {
              get
              {
                  if (_clock.IsRunning)
                  {
                      return _interval_clock.Elapsed.TotalMilliseconds;
                  }
                  else
                      return _loopTimeMs; ;
              }
          }

          private double _remainingTimeMs;
          internal double RemainingTimeMs
          {
              get
              {
                  if (_clock.IsRunning)
                      return CalculateRemainingTime();
                  else
                      return _remainingTimeMs;
              }
          }

          private double _totalTimeMs;
          internal double TotalTimeMs
          {
              get
              {
                  if (_clock.IsRunning)
                      return CalculateTotalTime();
                  else
                      return _totalTimeMs;
              }
          }

          internal TimeSpan LoopTime
          {
              get { return TimeSpan.FromMilliseconds(LoopTimeMs); }
          }

          internal TimeSpan TotalTime
          {
              get { return TimeSpan.FromMilliseconds(TotalTimeMs); }
          }

          internal TimeSpan RemainingTime
          {
              get { return TimeSpan.FromMilliseconds(RemainingTimeMs); }
          }


          // Methods

          internal void StartClock()
          {
              _clock.Start();
              _interval_clock.Start();

          }

          internal void StopClock()
          {
              _clock.Stop();
              _interval_clock.Stop();

              UpdateTimes();

              _interval_clock.Reset();

          }

          private void UpdateTimes()
          {
              //  reading clock
              double elapsed = _clock.Elapsed.TotalMilliseconds;

              // Calculating average loop time. The Stopwatch is not reseted between iterations.
              _loopTimeMs = elapsed / (Index + 1);

              // Calculating estimated remaining time =  average loop time * remaining iterations.
              _remainingTimeMs = CalculateRemainingTime();

              // Calculating estimated total time =  average loop time * iterations.
              _totalTimeMs = CalculateTotalTime();
          }

          private double CalculateRemainingTime()
          {
              // Calculating estimated remaining time =  average loop time * remaining iterations.

              double time;
              int countt = Count - Index;

              if (countt > 1)
                  time = LoopTimeMs * countt;
              else if (countt == 1)
                  time = LoopTimeMs;
              else
                  time = 0;

              return time;
          }

          private double CalculateTotalTime()
          {
              return LoopTimeMs * Count;
          }

          
      }
      // End Private helper class

      // Declarations
      private Dictionary<int,Loop> _loopDict;
      private int _loopIndex;

      // Constructor
      public LoopTimer()
      {
          _loopDict = new Dictionary<int,Loop>();
          _loopIndex = -1;
      }

      // Properties
      internal TimeSpan TotalTime
      {
          get { return TimeSpan.FromMilliseconds(TotalTimeMs); }
      }

      internal TimeSpan RemainingTime
      {
          get { return TimeSpan.FromMilliseconds(RemainingTimeMs); }
      }

      private double TotalTimeMs
      { get { return CalculateTotalTime(); } }

      private double RemainingTimeMs
      { get { return CalculateRemainingTime(); } }

      // Methods
      internal void EnterLoop(int index,int count)
      {
          Loop newLoop;

          // increase index
          _loopIndex++;

          if (!_loopDict.ContainsKey(_loopIndex))
          {
              // create new Loop
              newLoop = new Loop(index,count);
              _loopDict[_loopIndex] = newLoop;
          }
          else
          {   // retrieve Loop from Dict
              newLoop = _loopDict[_loopIndex];
          }

          newLoop.StartClock();
      }
 
      internal void EnterLoop(int index)
      {
          // increase index
          _loopIndex++;

          // retrive loop & start clock
          _loopDict[_loopIndex].Index = index;
          _loopDict[_loopIndex].StartClock();
      }

      internal void ExitLoop()
      {   // retrive loop & stop clock
          _loopDict[_loopIndex].StopClock();

          // decrease index
          _loopIndex--;
      }

      // bonus method
      internal TimeSpan ExitLoopRetETA()
      {  // retrive loop & stop clock
          _loopDict[_loopIndex].StopClock();

          // decrease index
          _loopIndex--;

          return RemainingTime;
      }

      // bonus method
      internal TotalEta ExitLoopRetTotalEta()
      {
          TotalEta retval;

          retval.Eta = ExitLoopRetETA();
          retval.Total = TotalTime;

          return retval;
      }

      // debug method
      internal void ShowStatus()
      {
          Console.WriteLine("Status:");
          Console.WriteLine(" RemainingTime:");
          for (int i = 0; i < _loopDict.Count; i++)
          {
              TimeSpan time = _loopDict[i].RemainingTime;
              Console.WriteLine(string.Format(" Loop: {0} Value: {1}",i,time.ToString()));
          }
          Console.WriteLine();
      }

      // debug method
      internal TotalEta[] GetStatus()
      {
          TotalEta[] retArr = new TotalEta[_loopDict.Count];
          TotalEta retval;

          for (int i = 0; i < _loopDict.Count; i++)
          {
              retval = new TotalEta();

              retval.Eta = _loopDict[i].RemainingTime;
              retval.Total = _loopDict[i].TotalTime;

              retArr[i] = retval;
          }
          return retArr;
      }

      private double CalculateRemainingTime()
      {
          double max,time;
          max = 0;

          // Remaining Time,the greater of all
          for (int i = 0; i < _loopDict.Count; i++)
          {
              time = _loopDict[i].RemainingTimeMs;
              if (time > max)
                  max = time;
          }

          return max;
      }

      // Total Time,bonus
      private double CalculateTotalTime()
      {
          double max,time;
          max = 0;

          // Total Time,the greater of all  
          for (int i = 0; i < _loopDict.Count; i++)
          {
              time = _loopDict[i].TotalTimeMs;
              if (time > max)
                  max = time;
          }

          return max;
      }
  }
}

示例程序:

using System;
using System.Threading;
using System.Threading.Tasks;


namespace LoopTimer
{
  class Solution
  {
      static CancellationTokenSource ts;

      static void Main(string[] args)
      {
          Console.Clear();

          LoopTimer lm = new LoopTimer();

          var random = new Random();

          // For easy change test parameters
          int minRndCount = 1;
          int maxRndCount = 10;
          int minRndSleep = 100;
          int maxRndSleep = 1000;

          // A task to update console,with cancellation token
          ts = new CancellationTokenSource();
          Task updater = new Task(() => DoUpdate(lm),ts.Token);
          // Uncomment to show estimated total time.
          //Task updater = new Task(() => DoUpdateTotal(lm),ts.Token);
          // Uncomment to show estimated total time and internal values of every loop.
          //Task updater = new Task(() => DoUpdateStatus(lm),ts.Token);

          // Simulate initiation delay
          Thread.Sleep(random.Next(minRndSleep,maxRndSleep));
          // Console.WriteLine("initiate");

          updater.Start();

          int intCountL1 = random.Next(minRndCount,maxRndCount);
          for (int loop1 = 0; loop1 <= intCountL1; loop1++)
          {
              // Entering loop1
              if (loop1 == 0)
                  lm.EnterLoop(loop1,intCountL1);
              else
                  lm.EnterLoop(loop1);

              // Simulate loop1 delay
              //Console.WriteLine("\tloop1");
              Thread.Sleep(random.Next(minRndSleep,maxRndSleep));

              int intCountL2 = random.Next(minRndCount,maxRndCount);
              for (int loop2 = 0; loop2 <= intCountL2; loop2++)
              {
                  // Entering loop2
                  if (loop2 == 0)
                      lm.EnterLoop(loop2,intCountL2);
                  else
                      lm.EnterLoop(loop2);

                  // Simulate loop2 delay
                  //Console.WriteLine("\t\tloop2");
                  Thread.Sleep(random.Next(minRndSleep,maxRndSleep));

                  int intCountL3 = random.Next(minRndCount,maxRndCount);
                  for (int loop3 = 0; loop3 <= intCountL3; loop3++)
                  {
                      // Entering loop3
                      if (loop3 == 0)
                          lm.EnterLoop(loop3,intCountL3);
                      else
                          lm.EnterLoop(loop3);

                      // Simulate loop3 delay
                      //Console.WriteLine("\t\t\tloop3");
                      Thread.Sleep(random.Next(minRndSleep,maxRndSleep));

                      int intCountL4 = random.Next(minRndCount,maxRndCount);
                      for (int loop4 = 0; loop4 <= intCountL4; loop4++)
                      {
                          // Entering loop4
                          if (loop4 == 0)
                              lm.EnterLoop(loop4,intCountL4);
                          else
                              lm.EnterLoop(loop4);

                          // Simulate loop4 delay
                          //Console.WriteLine("\t\t\t\tloop4");
                          Thread.Sleep(random.Next(minRndSleep,maxRndSleep));

                          // Exiting loop4
                          lm.ExitLoop();
                      }
                      // Exiting loop3
                      lm.ExitLoop();
                  }
                  // Exiting loop2
                  lm.ExitLoop();
              }
              // Exiting loop1
              lm.ExitLoop();
          }
          ts.Cancel();
      }

      static private void DoUpdate(LoopTimer lm)
      {
          char[] animchar = { '|','/','-','\\' };
          int index = 0;

          Thread.Sleep(100);

          while (true)
          {
              TimeSpan eta = lm.RemainingTime;

              Console.SetCursorPosition(0,0);
              Console.Write(string.Format(" {4} ETA: {0} Days,eta.Days.ToString().PadLeft(3,eta.Hours.ToString().PadLeft(2,eta.Minutes.ToString().PadLeft(2,eta.Seconds.ToString().PadLeft(2,animchar[index].ToString()));

              if (++index > 3)
                  index = 0;
              Thread.Sleep(1000);

              ts.Token.ThrowIfCancellationRequested();
          }
      }

      /*
        This method is provided as a sample on displaying the estimated total time.
       */
      static private void DoUpdateTotal(LoopTimer lm)
      {
          char[] animchar = { '|','\\' };
          int index = 0;

          Thread.Sleep(100);

          while (true)
          {
              TimeSpan eta = lm.RemainingTime;
              TimeSpan total = lm.TotalTime;

              Console.SetCursorPosition(0,animchar[index].ToString()));
              Console.Write(string.Format("\n Total: {0} Days,total.Days.ToString().PadLeft(3,total.Hours.ToString().PadLeft(2,total.Minutes.ToString().PadLeft(2,total.Seconds.ToString().PadLeft(2,'0')));

              if (++index > 3)
                  index = 0;
              Thread.Sleep(1000);

              ts.Token.ThrowIfCancellationRequested();
          }
      }

      /*
       This method is provided as a sample on displaying the estimated total time,and
       the internal values of every loop.
      */
      static private void DoUpdateStatus(LoopTimer lm)
      {
          char[] animchar = { '|','\\' };
          int index = 0;

          Thread.Sleep(100);

          while (true)
          {
              TimeSpan eta = lm.RemainingTime;
              TimeSpan total = lm.TotalTime;
              TotalEta[] status = lm.GetStatus();

              Console.SetCursorPosition(0,'0')));
              Console.WriteLine();

              int loop = 0;

              foreach (var item in status)
              {
                  Console.Write(string.Format("\n Loop: {0} ETA: {1}    \tTotal: {2}",loop,item.Eta.ToString(@"hh\:mm\:ss\.FFFF"),item.Total.ToString(@"hh\:mm\:ss\.FFFF")));
                  loop++;
              }

              if (++index > 3)
                  index = 0;

              Thread.Sleep(1000);

              ts.Token.ThrowIfCancellationRequested();
          }
      }

      /*
        This method is provided as a sample for variations on 
        the ExitLoopRet method. Uses in-place calls.
      */
      static internal void Bonus()
      {
          TotalEta remVal;
          TimeSpan remTime;

          LoopTimer lm = new LoopTimer();

          Console.Clear();

          // easy change test parameters
          var random = new Random();
          int minRndCount = 1;
          int maxRndCount = 5;

          int maxRndSleep = 1000;

         
          // First,outer loop
          int intCountL1 = random.Next(minRndCount,maxRndCount);

          for (int i = 0; i < intCountL1; i++)
          {
              if (i == 0)
                  lm.EnterLoop(i,intCountL1);
              else
                  lm.EnterLoop(i);

              Console.WriteLine(string.Format("\nLoop1 begin iteration: {0} of {1}. Will work(sleep) for {2} ms.",intCountL1 - 1,maxRndSleep));
              Thread.Sleep(maxRndSleep);

              // Second,middle loop
              int intCountL2 = random.Next(minRndCount,maxRndCount);

              for (int j = 0; j < intCountL2; j++)
              {
                  if (j == 0)
                      lm.EnterLoop(j,intCountL2);
                  else
                      lm.EnterLoop(j);

                  Console.WriteLine(string.Format("\n\tLoop2 begin iteration: {0} of {1}. Will work(sleep) for {2} ms.",j,intCountL2 - 1,maxRndSleep));
                  Thread.Sleep(maxRndSleep);

                  // Third,inner loop
                  int intCountL3 = random.Next(minRndCount,maxRndCount);
                  for (int k = 0; k < intCountL3; k++)
                  {
                      if (k == 0)
                          lm.EnterLoop(k,intCountL3);
                      else
                          lm.EnterLoop(k);

                      Console.WriteLine(string.Format("\n\t\tLoop3 begin iteration: {0} of {1}. Will work(sleep) for {2} ms.",k,intCountL3 - 1,maxRndSleep));
                      Thread.Sleep(maxRndSleep);

                      lm.ExitLoop();
                   
                      Console.WriteLine(string.Format("\n\t\tLoop3 end iteration: {0} of {1}",intCountL3 - 1));
                      lm.ShowStatus();
                  }

                  remTime = lm.ExitLoopRetETA();
                
                  Console.WriteLine(string.Format("\n\tLoop2 end iteration: {0} of {1}",intCountL2 - 1));
                  Console.WriteLine("\t\tRem: " + remTime.ToString());
              }

              remVal = lm.ExitLoopRetTotalEta();
              
              Console.WriteLine(string.Format("\nLoop1 end iteration: {0} of {1}",intCountL1 - 1));
              Console.WriteLine("\t\tTot: " + remVal.Total.ToString());
              Console.WriteLine("\t\tRem: " + remVal.Eta.ToString());
          }
      }

  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-