在不使用Thread.Sleep的情况下,大约每分钟运行一个任务

本文关键字:运行 每分钟 任务 一个 Thread Sleep 情况下 | 更新日期: 2023-09-27 18:25:42

我在C#中有一个要运行的方法,然后等待一分钟再重新启动该方法。

现在,我只是在使用

while(true)
{
    this.DoMyMethod();
    Thread.Sleep(TimeSpan.FromMinutes(1));
}

虽然这很有效,但我想知道是否有更优雅的方法可以做到这一点?定时器的问题是,即使最后一个定时器火警还没有结束,它们也会运行。

在不使用Thread.Sleep的情况下,大约每分钟运行一个任务

所以做一个异步循环:

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

该代码保证不会与DoMyMethod的调用重叠,因此延迟(与Thread.Sleep的方式大致相同)发生在调用之间。

如果您创建了一个CancellationTokenSource,您可以将其Token传递给您的方法,并可以通过在CancellationTokenSource上调用Cancel来终止循环。

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

使用System.Timers.Timer,您可以将AutoReset设置为false,这意味着计时器只运行一次,您必须再次调用Start()才能重新启动它。

因此,在您的计时器刻度方法中,只需在完成所需操作并准备重新开始后调用Start()即可。

例如:

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
}

计时器仍然是您的选择。如果您担心它在第一个计时器启动过程完成之前再次跳闸,请在进程运行时停止计时器,然后在进程完成时重新启动。