简体   繁体   English

大约每分钟运行一次任务而不使用Thread.Sleep

[英]Running a task approximately every minute without using Thread.Sleep

I have a method in C# that I would run, then wait a minute before restarting the method again. 我在C#中有一个方法可以运行,然后等一下再重新启动方法。

Right now, I am just using 现在,我正在使用

while(true)
{
    this.DoMyMethod();

    Thread.Sleep(TimeSpan.FromMinutes(1));
}

While this works, I am wondering if there is a more elegant way of doing this? 虽然这有效,但我想知道是否有更优雅的方式来做到这一点? The issue with Timers, is they'll run even if the last timer fire call hasn't finished yet. 计时器的问题是,即使最后一次定时器点火呼叫尚未完成,它们也会运行。

So make an asynchronous loop: 所以做一个异步循环:

public async Task DoMyThing(CancellationToken token = default(CancellationToken))
{
     while(!token.IsCancellationRequested)
     {
         this.DoMyMethod();
         try
         {
             await Task.Delay(TimeSpan.FromMinutes(1), token);
         }
         catch(TaskCanceledException)
         {
             break;
         }
     }
}

This code is guaranteed not to overlap the invocations of DoMyMethod , so the delay (much in the same way as Thread.Sleep ) happens between invocations. 保证此代码不会与DoMyMethod的调用重叠,因此调用之间会发生延迟(与Thread.Sleep非常相似)。

If you create a CancellationTokenSource , you can pass its Token to your method and you can kill the loop by calling Cancel on the CancellationTokenSource . 如果您创建了CancellationTokenSource ,则可以将其Token传递给您的方法,并且可以通过在CancellationTokenSource上调用Cancel来终止循环。

Note: CancellationToken.None === default(CancellationToken) 注意: CancellationToken.None === default(CancellationToken)

With System.Timers.Timer you can set AutoReset to false meaning the timer will only run once, you'd have to call Start() again to restart it. 使用System.Timers.Timer您可以将AutoReset设置为false这意味着计时器只运行一次,您必须再次调用Start()来重新启动它。

So in your timer tick method simply call Start() after you've done what you need to and you're ready to begin again. 因此,在您的计时器滴答方法中,只需在完成所需操作后调用Start() ,然后您就可以重新开始了。

For example: 例如:

public SomeClass()
{
    Timer timer = new Timer(60000);
    timer.Elapsed += new ElapsedEventHandler(OnElapsed);
    timer.AutoReset = false;
    timer.Start();
}

private void OnElapsed(object sender, ElapsedEventArgs e)
{
    // Do stuff

    timer.Start(); // Restart timer
}

A timer is still your option. 计时器仍然是您的选择。 If you are concerned about it tripping again before the first timer firing process has completed, the stop the timer while the process runs, and then restart it when your process completes. 如果您担心在第一个定时器触发过程完成之前再次跳闸,则在过程运行时停止定时器,然后在过程完成时重新启动定时器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM