【问题标题】:Calling a method every x minutes每 x 分钟调用一次方法
【发布时间】:2012-10-22 20:36:21
【问题描述】:

我想每 5 分钟调用一次方法。我该怎么做?

public class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("*** calling MyMethod *** ");
        Console.ReadLine();
    }

    private MyMethod()
    {
        Console.WriteLine("*** Method is executed at {0} ***", DateTime.Now);
        Console.ReadLine();
    }
}

【问题讨论】:

标签: c#


【解决方案1】:
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromMinutes(5);

var timer = new System.Threading.Timer((e) =>
{
    MyMethod();   
}, null, startTimeSpan, periodTimeSpan);

【讨论】:

  • 另一种设置间隔的方法是传入一个时间跨度对象。我认为它更干净一点:Timespan.FromMinutes(5)
  • @MichaelHaren 我不知道,这很好。谢谢!
  • @asawyer 不幸的是,您的实现给出了编译错误。 TotalMilliseconds 返回一个 double 而计时器需要整数或 TimeSpan。我试图将您的答案更新为使用TimeSpan 并抛出不必要的膨胀;但是,您将其还原。
  • @AndréChristofferAndersen 将 Time 构造函数中的 0 更改为 TimeSpan.Zero。代码在此之后工作。
  • 代码出错。这是修复 new System.Threading.Timer((e) => { Func(); }, null, TimeSpan.Zero, TimeSpan.FromMinutes(1).TotalMilliseconds);
【解决方案2】:

我基于@asawyer 的回答。他似乎没有遇到编译错误,但我们中的一些人会。这是 Visual Studio 2010 中的 C# 编译器将接受的版本。

var timer = new System.Threading.Timer(
    e => MyMethod(),  
    null, 
    TimeSpan.Zero, 
    TimeSpan.FromMinutes(5));

【讨论】:

  • 为后代评论。当您在计时器对象上调用Dispose() 方法时,它将停止。示例:timer.Dispose() 使用上面的代码作为参考。但是,这会破坏计时器并阻止您再次使用它。如果您想在同一程序中再次使用计时器,timer.Change(Timeout.Infinite, Timeout.Infinite) 会更好。
  • 但是为什么我在控制台应用程序中运行 MyMethod() 没有运行
  • @Izuagbala 如果不了解您的设置细节,很难说为什么它不适合您。此解决方案已在控制台应用程序中进行了测试。
  • 什么是空值?
  • @DanielReyhanian 您可以添加一个对象状态而不是null,即作为调用回调函数时的参数(即第一个参数)。
【解决方案3】:

在类的构造函数中启动一个计时器。 间隔以毫秒为单位,因此 5*60 秒 = 300 秒 = 300000 毫秒。

static void Main(string[] args)
{
    System.Timers.Timer timer = new System.Timers.Timer();
    timer.Interval = 300000;
    timer.Elapsed += timer_Elapsed;
    timer.Start();
}

然后像这样在timer_Elapsed 事件中调用GetData()

static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    //YourCode
}

【讨论】:

    【解决方案4】:

    我上传了一个 Nuget 包,它可以让它变得如此简单,你可以从这里获得它ActionScheduler

    它支持 .NET Standard 2.0

    以及如何开始使用它

    using ActionScheduler;
    
    var jobScheduler = new JobScheduler(TimeSpan.FromMinutes(8), new Action(() => {
      //What you want to execute
    }));
    
    jobScheduler.Start(); // To Start up the Scheduler
    
    jobScheduler.Stop(); // To Stop Scheduler from Running.
    

    【讨论】:

    • 无法安装包'CrystalJobScheduler 1.0.0'。您正在尝试将此包安装到以“.NETFramework,Version=v4.5”为目标的项目中,但该包不包含任何与该框架兼容的程序集引用或内容文件。如需更多信息,请联系包作者。
    【解决方案5】:

    Timer 使用示例:

    using System;
    using System.Timers;
    
    static void Main(string[] args)
    {
        Timer t = new Timer(TimeSpan.FromMinutes(5).TotalMilliseconds); // Set the time (5 mins in this case)
        t.AutoReset = true;
        t.Elapsed += new System.Timers.ElapsedEventHandler(your_method);
        t.Start();
    }
    
    // This method is called every 5 mins
    private static void your_method(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("..."); 
    }
    

    【讨论】:

      【解决方案6】:

      使用TimerTimer documentation.

      【讨论】:

        【解决方案7】:

        更新 .NET 6

        对于 dotnet 6+ 中的大多数用例,您应该使用 PeriodicTimer

        var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));
        
        while (await timer.WaitForNextTickAsync())
        {
            //Business logic
        }
        

        这有几个优点,包括异步/等待支持,避免回调造成的内存泄漏,以及CancelationToken 支持

        进一步阅读

        【讨论】:

          【解决方案8】:

          使用 DispatcherTimer:

           var _activeTimer = new DispatcherTimer {
             Interval = TimeSpan.FromMinutes(5)
           };
           _activeTimer.Tick += delegate (object sender, EventArgs e) { 
             YourMethod(); 
           };
           _activeTimer.Start();          
          

          【讨论】:

            【解决方案9】:

            如果需要linux cron等更复杂的时间执行,可以使用NCrontab。

            我在生产中使用 NCrontab 很长时间了,效果很好!

            Nuget

            使用方法:

            * * * * *
            - - - - -
            | | | | |
            | | | | +----- day of week (0 - 6) (Sunday=0)
            | | | +------- month (1 - 12)
            | | +--------- day of month (1 - 31)
            | +----------- hour (0 - 23)
            +------------- min (0 - 59)
            
            using NCrontab;
            //...
            
            protected override async Task ExecuteAsync(CancellationToken stoppingToken)
            {
              // run every 5 minutes
              var schedule = CrontabSchedule.Parse("*/5 * * * *");
              var nextRun = schedule.GetNextOccurrence(DateTime.Now);
              logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);    
              do
              {
                if (DateTime.Now > nextRun)
                {
                  logger.LogInformation("Sending notifications at: {time}", DateTimeOffset.Now);
                  await DoSomethingAsync();
                  nextRun = schedule.GetNextOccurrence(DateTime.Now);
                }
                await Task.Delay(1000, stoppingToken);
              } while (!stoppingToken.IsCancellationRequested);
            }
            

            如果需要,添加秒数:

            // run every 10 secs
            var schedule = CrontabSchedule.Parse("0/10 * * * * *", new CrontabSchedule.ParseOptions { IncludingSeconds = true });
            

            【讨论】:

              【解决方案10】:
              while (true)
              {
                  Thread.Sleep(60 * 5 * 1000);
                  Console.WriteLine("*** calling MyMethod *** ");
                  MyMethod();
              }
              

              【讨论】:

              • 是的,如果有任何使用 await Task.Delay(60 * 5 * 1000);
              • 我喜欢这个答案,比上面的任何 Timer 都简单。
              • 我认为睡眠会使整个应用程序冻结!
              猜你喜欢
              • 2014-03-14
              • 2011-06-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多