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

osh*_*nen 5 .net c# datetime .net-core

更新1:

下面提供的一些解决方案看起来不错。但是,我只知道循环在其父循环的迭代确定后迭代的次数。所以我不能事先计算所有的迭代。

原问题:

我在一个类似的程序中嵌入了循环:

程序 1:

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));
                        }
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试显示剩余处理时间 (ETA),因此我可以看到对上述循环序列完成之前剩余时间的粗略估计

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

程序2:

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,'0'), timeRemaining.Minutes.ToString().PadLeft(2,'0'), timeRemaining.Seconds.ToString().PadLeft(2,'0')));
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试将 Prog1 的 ETA 方面合并到 Prog2 中时,它似乎效果不佳:

Prog3 = Prog1+Prog2:

using System;
using System.Threading;

namespace time_remaining_loop_strip
{
    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)
        {
            DateTime startTime = DateTime.Now;
            
            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));
                        }
                    }
                }

                TimeSpan timeRemaining = ComputeRemaining((0, startTime), (loop1, DateTime.Now), intCount);

                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,'0'), timeRemaining.Minutes.ToString().PadLeft(2,'0'), timeRemaining.Seconds.ToString().PadLeft(2,'0')));
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎根本不起作用。它确实显示了 ETA,但由于循环的结构方式,它在显示任何内容之前有很长时间的延迟。

我如何更新它,以便 ETA 代码更准确地以更具预测性的间隔显示 ETA,就像每秒一样?

小智 0

您可以知道循环 4 (L4) 将执行多少次 (t) 乘法 L1t L2t L3t*L4t = 总计。现在你从一开始就声明

dt = DateTime.Now;
count = 0L;
Run Code Online (Sandbox Code Playgroud)

现在在 L4 中增加计数并计算经过了多少时间

et= DateTime.Now - dt;
count++;
Run Code Online (Sandbox Code Playgroud)

并使用三规则计算还剩多少秒才能达到总迭代次数。

remainingSeconds = (total*et.TotalSeconds/count) - et.TotalSeconds;
Run Code Online (Sandbox Code Playgroud)

现在预计到达时间是

DateTime.Now.AddSeconds(remainingSeconds);
Run Code Online (Sandbox Code Playgroud)