每隔x分钟调用一个方法

144

我想每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();
    }
}

10
System.Threading.Timer:这是一个.NET Framework中的类,用于创建计时器对象,以在一段时间后执行指定的回调函数。 - user703016
1
或者 System.Timers.Timer - http://www.dotnetperls.com/timer - Sinan AKYAZICI
11个回答

224
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromMinutes(5);

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

编辑 - 这个回答已经过时。请查看https://dev59.com/EWcs5IYBdhLWcg3wPxge#70887955


28
设定时间间隔的另一种方法是传递一个时间段对象。我认为这样会更加简洁:Timespan.FromMinutes(5) - Michael Haren
我认为TimeSpan对象存在问题,因为它与0, 5 * 60 * 1000不是相同的类型。无论如何,对于我来说,它会生成一个错误。 - amiregelz
4
很抱歉,您的实现出现了编译错误。TotalMilliseconds返回的是一个double类型,而计时器(timer)需要整数或TimeSpan类型。我尝试更新您的答案,使用TimeSpan并删除不必要的冗余代码,但您将其还原了。 - André C. Andersen
2
@AndréChristofferAndersen 将Time构造函数中的0更改为TimeSpan.Zero。 更改后代码可以正常工作。 - RredCat
2
代码出现错误。这是修复方法:new System.Threading.Timer((e) => { Func(); }, null, TimeSpan.Zero, TimeSpan.FromMinutes(1).TotalMilliseconds); - Asheh
显示剩余9条评论

63

我基于@asawyer的回答进行了修改。他似乎没有遇到编译错误,但我们中的一些人却遇到了。这是一个在Visual Studio 2010中C#编译器能够接受的版本。

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

12
为了记录下来,留下评论。当你调用定时器对象的Dispose()方法时,定时器将会停止。例如:使用上述代码作为参考,调用timer.Dispose()方法。这将销毁定时器并防止你再次使用它。如果你想在同一程序中再次使用定时器,最好使用timer.Change(Timeout.Infinite, Timeout.Infinite) - Joel Trauger
1
但是为什么当我在控制台应用程序中运行MyMethod()时它不会运行呢? - Izuagbala
@Izuagbala 如果不知道您如何设置,很难说为什么它对您无效。此解决方案已在控制台应用程序中进行了测试。 - André C. Andersen
什么是 null? - Daniel Reyhanian
@DanielReyhanian 你可以添加一个对象状态来代替null,作为调用回调函数时的参数(即第一个参数)。 - André C. Andersen

50

更新 .NET 6

在大多数使用 dotnet 6+ 的情况下,您应该使用 PeriodicTimer

var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));

while (await timer.WaitForNextTickAsync())
{
    //Business logic
}

这种方法有很多优点,包括支持异步/等待、避免回调造成的内存泄漏以及CancelationToken支持。

进一步阅读


13

在您的类构造函数中启动一个定时器。 时间间隔以毫秒为单位,因此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
}

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("..."); 
}

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'的项目中,但该包不包含任何与该框架兼容的程序集引用或内容文件。有关更多信息,请联系包作者。 - Aditya Bokade

3

2

使用DispatcherTimer:

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

只是想指出,如果你想每隔“x”秒做一次,那么你可以使用“TimeSpan.FromSeconds(x)” - Prabhdeep Singh
2
是的,但是原帖作者需要在几分钟内得到它。 :) - Bloggrammer

1

可以通过应用 while 循环并在循环结束时调用 Thread.Sleep 来实现。

while (true)
{
    //Your code
    Thread.Sleep(5000);
}

请确保包含 using System.Threading


1
如果您需要更复杂的时间执行,例如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 });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接