Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计时器以秒为单位精确计时_C#_Task Parallel Library_Infinite Loop_.net Core_Timespan - Fatal编程技术网

C# 计时器以秒为单位精确计时

C# 计时器以秒为单位精确计时,c#,task-parallel-library,infinite-loop,.net-core,timespan,C#,Task Parallel Library,Infinite Loop,.net Core,Timespan,我试图和其他代码并行运行一个无限循环,它在一个特定的时间内以秒为单位执行一次。 在下面的代码中,我试图触摸精确的午夜时间,即:00 hh:00 mm:00秒 using System; // for Date/Time using System.Threading.Tasks; // for Parallel public class Program { public static void Main(string[] args) { Parallel.Invoke( () =>

我试图和其他代码并行运行一个无限循环,它在一个特定的时间内以秒为单位执行一次。 在下面的代码中,我试图触摸精确的午夜时间,即:00 hh:00 mm:00秒

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
我能够使
wait
语句正确工作以达到所需的点,但是锁定条件
if(duration==TimeSpan.Zero)
从未变为
true

我可以通过改变以下条件来实现:

if(duration == TimeSpan.Zero)
致:

为了避免事件重复发生,我添加了另一个
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);
我尝试添加
如果(duration.millizes>=1)等待(1)
,但没有成功,我的输出如下所示:

问题是,在您的情况下,
持续时间从来都不是零,它从加数毫秒变为减数毫秒

我要做的是:如果
持续时间
小于1秒,等待
持续时间
,然后假设这是正确的时间。代码:

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);
}

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

首先,你的程序不能像你显示的那样工作,因为你的
TimeSpan duration=DateTime.Parse(午夜)。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获得更好的精度,但类似的解决方案要复杂得多)

也作为概念教授

时间版本:

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);
    }
}
使用系统;
使用系统线程;
使用System.Threading.Tasks;
公共课程
{
公共静态void Main(字符串[]args)
{
并行调用(
异步()=>
{
Console.WriteLine(“开始第二个任务…”);
TimeSpan eventTime=新的TimeSpan(0,18,16,53123);//运行事件时设置(例如18:16:53.123)
DateTime endDate=DateTime.Today.Add(eventTime);

如果(enddate)如果我读对了,如果剩下不到一分钟,您仍然会延迟一秒钟(
等待任务。延迟(1000);
)?即使只有半秒?这可能是你的问题。如果你使用一个计划的任务来完成这项任务,它会有帮助吗?Quartz.NET是一个库,它可能会帮助你…也可以看到:值得注意的是,除非你能完全确定循环每毫秒会运行几次,否则你试图做的事情可能是不可能的因素(例如垃圾收集)可能会干扰。您最好在到达或经过的时间内设置一个标志。这里有一个不相关但潜在的严重错误:您正在使用
async
lambda作为
Parllel.Invoke
的参数,它不提供异步支持。第二个参数(
Func
)只会一直阻止,直到您点击
await
语句。如果您的第一个
操作恰好在那时完成,
Parallel.Invoke
将完成,程序将立即终止,而无需等待
async
委托创建的
任务完成。没有确切的时间。这是宇宙量子性质的结果。你到底想做什么?你到底需要走多远?你可能想做
等待任务。延迟(TimeSpan.FromDays(1));
等待任务。延迟(TimeSpan.FromHours(1))
等等,使其更易于阅读。从技术角度来看,您的方法是错误的,因为您的应用程序最终不会说“是时候了”如果在午夜冻结2秒。@Logman,看起来它真的冻结了,但为什么会发生这种情况,仍然没有理解它。@HasanAYousef因为你可能使用普通的计算机而不是RTC系统,所以你不能依赖精确的时间。你的应用程序无法工作可能有多种原因,但检查现在是否是午夜的整个想法是错误的ng.其中一个解决方案是检查你是否过了午夜,然后做点什么并重置计时器。另外,
任务。延迟
不保证它会精确等待N毫秒,只保证它至少会等待N毫秒。#Logman能否请你发布一个建议的解决方案,让我测试一下。谢谢你的方法看起来很有逻辑,我会仔细检查星期天,星期一前确认。谢谢如果我想将它与给定的时间进行比较,而不是午夜,该怎么办?@HasanAYousef我有一个小错误(我混合了10s版本和午夜版本)但现在没关系。现在来回答你的问题。你需要计算endDate而不是startDate。然后在持续时间超过0后,你需要重新计算它并完成你的工作。我将在一分钟后发布示例。但为了将来,请将你的需求与你的问题一起发布,不要在以后添加它们,因为它们可能会完全改变实现。@HasanAYousef我添加了新版本。非常感谢,它现在非常完美,我可以达到每毫秒的精度:)请考虑你的备忘录,谢谢。@ Hasayayousf不受欢迎。准确性将严重依赖于你运行Exp的应用程序。如果你在后台进行,用户正在玩电子游戏,在你的应用程序执行你的事件之前可能还要几秒钟。如果你对我的AN满意的话,请再投票。回答。
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);
    }
}