定时器以秒为准确的时间

时间:2016-11-03 10:01:00

标签: c# task-parallel-library infinite-loop .net-core timespan

我正在尝试与其他代码并行运行无限循环,这是在SECOND实现的特定时间执行的。 在下面的代码中,我试图触摸确切的午夜时间,即:00 hh:00 mm:00 sec

using System;  // for Date/Time
using System.Threading.Tasks;  // for Parallel

public class Program
{
public static void Main(string[] args)
{
Parallel.Invoke(
() =>
     {
           Console.WriteLine("Begin first task...");
      },  // close first Action

async () =>
      {
         Console.WriteLine("Begin second task...");
         var midNight = "00:00:00";
         while (true)
            {
              TimeSpan duration = DateTime.Parse(midNight).Subtract(DateTime.Now);
              Console.WriteLine("looping at: {0:00} Days, {1:00} Hours, {2:00} Minutes, {3:00} Seconds, {4:00} Milliseconds", 
              duration.Days, duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);

              if(duration.Days >= 1)
                await Task.Delay(8640000);
                    else if(duration.Hours >= 1)
                           await Task.Delay(360000);
                               else if(duration.Minutes >= 1)
                                      await Task.Delay(60000);
                                         else 
                                            await Task.Delay(1000);

              if(duration == TimeSpan.Zero) { 
                  Console.WriteLine("It is time... midnight is {0}", DateTime.Now);
    }  // close second Action `the async task`
)  // end of Parallel.Invoke
}  // End of Main
}  // End of Program

我能够使await语句正常工作以达到所需的点,但锁定条件if(duration == TimeSpan.Zero)永远不会成为true enter image description here

3 个答案:

答案 0 :(得分:2)

首先,您的计划无法正常展示,因为您的TimeSpan duration = DateTime.Parse(midNight).Subtract(DateTime.Now);永远不会是积极的。其次你的主要功能几乎会立即返回。无论如何,你可以尝试我的解决方案来解决你的问题:

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

public class Program
{

    public static void Main(string[] args)
    {
        Parallel.Invoke(
            () =>{Console.WriteLine("Begin first task...");},
            async () =>
            {
                Console.WriteLine("Begin second task...");
                DateTime startDate = DateTime.Today;
                while (true)
                {
                    TimeSpan duration = DateTime.Now.Subtract(startDate);
                    Console.WriteLine("looping at: {0:00} Days, {1:00} Hours, {2:00} Minutes, {3:00} Seconds, {4:00} Milliseconds", 
                                      duration.Days, duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);

                    int delay = (int)(DateTime.Today.AddDays(1.0).Subtract(DateTime.Now).TotalMilliseconds/2);
                    await Task.Delay(delay>0?delay:0);

                    if(duration.Days >= 1) 
                    { 

                        Console.WriteLine("It is time... midnight is {0}", DateTime.Now);

                        startDate = DateTime.Today;
                    }

                }
            }
        );
    }
}

这不会为您提供超级精确度,因为在普通PC上您无法获得它(您可以使用IRQ获得更高的准确度,但这样的解决方案要复杂得多)。

同样作为概念教授link to 10s version

时间版:

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

public class Program
{

    public static void Main(string[] args)
    {
        Parallel.Invoke(
            async () =>
            {
                Console.WriteLine("Begin second task...");
                TimeSpan eventTime = new TimeSpan(0,18,16,53,123); //set when run event (ex. 18:16:53.123)
                DateTime endDate = DateTime.Today.Add(eventTime);
                if(endDate<DateTime.Now) endDate = endDate.AddDays(1.0);
                while (true)
                {
                    TimeSpan duration = endDate.Subtract(DateTime.Now);
                    Console.WriteLine("looping at: {0:00} Days, {1:00} Hours, {2:00} Minutes, {3:00} Seconds, {4:00} Milliseconds", duration.Days, duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);

                    if(duration.TotalMilliseconds <= 0.0)
                    { 
                        Console.WriteLine("It is time... {0}", DateTime.Now);

                        endDate = endDate.AddDays(1.0);
                        continue;
                    }

                    int delay = (int)(duration.TotalMilliseconds/2);
                    await Task.Delay(delay>0?delay:0);

                }
            }
        );
        Thread.Sleep(6000);
    }
}

答案 1 :(得分:0)

我能够通过改变条件来实现:

if(duration == TimeSpan.Zero)

为:

if(duration.Days == 0 && duration.Hours == 0 && duration.Minutes == 0 && duration.Seconds == 0)

为了避免事件的双重发生,我添加了另一个await级别,因此新的级别变为:

if(duration.Days >= 1)
   await Task.Delay(8640000);
      else if(duration.Hours >= 1)
         await Task.Delay(360000);
            else if(duration.Minutes >= 1)
                await Task.Delay(60000);
                   else if(duration.Seconds >= 1)
                      await Task.Delay(1000);
                          else
                              await Task.Delay(500);

我尝试添加if(duration.Milliseconds >= 1) await(1)但是没有用,我的输出如下所示: enter image description here

答案 2 :(得分:0)

问题在于,在你的情况下,duration永远不会为零,它从加上几毫秒到减去几毫秒。

我会做什么:如果duration小于一秒,请等待duration,然后假设它是正确的时间。在代码中:

if (duration.Days >= 1)
    await Task.Delay(8640000);
else if (duration.Hours >= 1)
    await Task.Delay(360000);
else if (duration.Minutes >= 1)
    await Task.Delay(60000);
else if (duration.Seconds >= 1)
    await Task.Delay(1000);
else
{
    // defensive check in case duration is already negative
    // this should not normally happen, but is still possible
    if (duration > TimeSpan.Zero)
        await Task.Delay(duration);
    Console.WriteLine("It is time... midnight is {0}", DateTime.Now);
}

这不会给你毫秒的准确度,但在正常情况下它应该是正确的秒。