2009-02-01 56 views
1

我想要一种能够安排回调的方法,我希望能够在不同的时间向“计划程序”对象注册许多不同的回调。像这样的东西。安排代表电话

public class Foo 
{ 
    public void Bar() 
    { 
     Scheduler s = new Scheduler(); 
     s.Schedule(() => Debug.WriteLine("Hello in an hour!"), DateTime.Now.AddHours(1)); 
     s.Schedule(() => Debug.WriteLine("Hello a week later!"), DateTime.Now.AddDays(7)); 
    } 
} 

我能想出的实施计划,最好的办法是在给定的时间间隔内运行的每个间隔结束时我检查已注册的回调,看看它的时间打电话给他们一个计时器,如果是这样的话。这很简单,但缺点是只能得到定时器的“分辨率”。假设定时器设置为每秒一次,并且注册一个半秒钟内调用的回调函数,它仍然可能不会被调用一整秒。

有没有更好的方法来解决这个问题?

回答

2

这是一个很好的方法。一旦下一个事件发生,您应该动态设置定时器关闭。您可以通过将作业放入优先队列来完成此任务。毕竟,在任何情况下你都是总是限制在系统可以提供的分辨率,但是你应该编码,以便它只是只有的限制因素。

+0

我发誓我想到这个解决方案,我点击发送按钮的问题。很高兴知道这是正确的方法。 – 2009-02-01 20:08:47

1

一个很好的方法是改变你的计时器的持续时间:告诉它在你的第一个/下一个预定事件到期时(但不是在)之前关闭。

<有关不Windows中的实时操作系统,因此它的定时器必须始终都有点不准确>

1

你只有真正需要的调度时earlest醒来,执行什么标准免责声明清单上的项目应到期。之后,您将设置计时器,以便下次唤醒计划程序。

添加新项目时,只需将其时间表与当前正在等待的项目进行比较即可。如果它早些时候取消当前计时器并将新项目设置为下一个计划项目。

0

下面是我写的一个类,使用.NET的内置Timer类来完成这个任务。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace Sample 
{ 
    /// <summary> 
    /// Use to run a cron job on a timer 
    /// </summary> 
    public class CronJob 
    { 
     private VoidHandler cronJobDelegate; 
     private DateTime? start; 
     private TimeSpan startTimeSpan; 
     private TimeSpan Interval { get; set; } 

     private Timer timer; 

     /// <summary> 
     /// Constructor for a cron job 
     /// </summary> 
     /// <param name="cronJobDelegate">The delegate that will perform the task</param> 
     /// <param name="start">When the cron job will start. If null, defaults to now</param> 
     /// <param name="interval">How long between each execution of the task</param> 
     public CronJob(VoidHandler cronJobDelegate, DateTime? start, TimeSpan interval) 
     { 
      if (cronJobDelegate == null) 
      { 
       throw new ArgumentNullException("Cron job delegate cannot be null"); 
      } 

      this.cronJobDelegate = cronJobDelegate; 
      this.Interval = interval; 

      this.start = start; 
      this.startTimeSpan = DateTime.Now.Subtract(this.start ?? DateTime.Now); 

      this.timer = new Timer(TimerElapsed, this, Timeout.Infinite, Timeout.Infinite); 
     } 

     /// <summary> 
     /// Start the cron job 
     /// </summary> 
     public void Start() 
     { 
      this.timer.Change(this.startTimeSpan, this.Interval); 
     } 

     /// <summary> 
     /// Stop the cron job 
     /// </summary> 
     public void Stop() 
     { 
      this.timer.Change(Timeout.Infinite, Timeout.Infinite); 
     } 

     protected static void TimerElapsed(object state) 
     { 
      CronJob cronJob = (CronJob) state; 
      cronJob.cronJobDelegate.Invoke(); 
     } 
    } 
} 
+0

感谢分享。虽然它不是我正在寻找的东西,因为我想用一个实例安排多个回调,所以非常高兴看看您的代码以获取灵感。 – 2009-02-01 20:18:37

0

Quartz.Net作业调度程序。然而,这是安排班级而不是代表。