Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.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#_.net_Multithreading_.net 4.0_Timer - Fatal编程技术网

C# 等待计时器,每间隔运行一次?

C# 等待计时器,每间隔运行一次?,c#,.net,multithreading,.net-4.0,timer,C#,.net,Multithreading,.net 4.0,Timer,使用C#,.NET Framework 4.0。 我有3个TimeSpan对象,分别设置为20分钟、30分钟和45分钟。我想让计时器只以精确的分钟间隔执行,而不管任何计时器何时实际启动。 我需要让计时器按如下方式启动(每小时): 我认为一个可等待的计时器是正确的选择,但由于缺乏简单的例子,我想不是。获得此功能的最佳方法是什么(如果可能的话,我希望避免时钟漂移,但我现在迫切需要任何东西)?我没有嫁给服务员。我也知道timerC每小时只运行一次,这很好,因为它被设置为只在每小时的第45分钟运行 注意

使用C#,.NET Framework 4.0。 我有3个TimeSpan对象,分别设置为20分钟、30分钟和45分钟。我想让计时器只以精确的分钟间隔执行,而不管任何计时器何时实际启动。 我需要让计时器按如下方式启动(每小时):

我认为一个可等待的计时器是正确的选择,但由于缺乏简单的例子,我想不是。获得此功能的最佳方法是什么(如果可能的话,我希望避免时钟漂移,但我现在迫切需要任何东西)?我没有嫁给服务员。我也知道timerC每小时只运行一次,这很好,因为它被设置为只在每小时的第45分钟运行

注意-我还没有准备好使用Quartz.NET


谢谢。

我能得到的最接近的方法是使用waitable(sleep()、带超时的事件、一些线程计时器或经典的“主线程窗口计时器”)在目标时间上“爬行”,设置为“现在”和目标时间之间的毫秒数的一半,这是根据实时时钟计算的。如果剩余ms大于某个限制(例如500),请重新校准剩余ms并再次等待。当剩余毫秒低于限制时,开始在实时时钟上循环,直到达到或超过目标,然后调用TimeSpan对象的timeout()方法

您可以将TimeSpan对象放入超时时间顺序队列中,这样您只需要一个等待对象。如果您遇到TimeSpan事件经常“同时”发生的情况,这可能更准确,因为目标时间接近时只有一个线程循环

Rgds,
马丁

我想这会帮你完成工作:

static void Main(string[] args)
{
    StartTimer(TimeSpan.FromMinutes(20.0), "TimerA", true);
    StartTimer(TimeSpan.FromMinutes(30.0), "TimerB", true);
    StartTimer(TimeSpan.FromMinutes(45.0), "TimerC", true);

    Console.WriteLine("Press any key to exit...");
    Console.ReadLine();
}
start timer函数启动计时器并返回它(如果需要引用)。这里的关键是你给它一个计时器名称,然后告诉它你是否想把计时器调整到整小时。如果您不想与整小时对齐,则计时器将立即以指定的频率启动

public static Timer StartTimer(TimeSpan frequency, string timerName, bool alignToHour)
{
    if (alignToHour)
    {
        return new Timer(OnTimerTick, timerName, ComputeDelay(frequency), frequency);
    }
    else
    {
        return new Timer(OnTimerTick, timerName, TimeSpan.Zero, frequency);
    }
}
计时器滴答作响时将触发的函数

public static void OnTimerTick(object state)
{
    Console.WriteLine((string)state + " " + DateTime.Now.ToString("H:mm"));
}
此方法计算计时器必须在整小时内对齐时所需的延迟。仅当频率小于一小时或大于一分钟时,此功能才有效

public static TimeSpan ComputeDelay(TimeSpan frequency)
{
    if (frequency > TimeSpan.FromHours(1.0) || 
        frequency < TimeSpan.FromMinutes(1.0))
    {
        throw new ArgumentException(
            "The frequency cannot be more than one hour or less than one minute!");
    }

    return frequency - TimeSpan.FromMinutes(DateTime.Now.Minute % frequency.Minutes);
}
公共静态时间跨度计算延迟(时间跨度频率)
{
如果(频率>时间跨度从小时(1.0)|
频率<时间跨度从分钟(1.0))
{
抛出新的ArgumentException(
“频率不能超过一小时或少于一分钟!”;
}
返回频率-TimeSpan.FromMinutes(DateTime.Now.Minute%frequency.Minutes);
}

注意:在您的示例中,您以1小时的频率运行45分钟计时器,但您分别以20分钟和30分钟的频率运行20分钟和30分钟计时器。我的代码不适用于频率为1小时的45分钟计时器,但它适用于频率为20、30和45分钟的计时器。我不确定你的例子是否错了,但如果它没有错,那么我认为你应该能够从现在开始找出如何处理这种差异。

你能解释一下你想做什么吗?@Snowy,你在使用什么编程语言。网?此外,在您的示例中,计时器C每小时执行一次,而不是每45分钟执行一次。。。这就是你真正想要的吗?只使用一个计时器,这样它们就永远不会分开。将其设置为下一个到期时间间隔,然后确定需要执行的操作。总是从时钟开始计算时间间隔,永远不要增加一个增量,因为那总是会变晚。@Hans,我不确定他是否真的需要这么精确,他似乎想要分钟精度(似乎是他暗示的,他说的是精确的分钟间隔)。你可能对C中的可等待计时器感兴趣:。代码可在
public static TimeSpan ComputeDelay(TimeSpan frequency)
{
    if (frequency > TimeSpan.FromHours(1.0) || 
        frequency < TimeSpan.FromMinutes(1.0))
    {
        throw new ArgumentException(
            "The frequency cannot be more than one hour or less than one minute!");
    }

    return frequency - TimeSpan.FromMinutes(DateTime.Now.Minute % frequency.Minutes);
}