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));
    }
}

我能想出的实现调度程序的最佳方法是以给定的间隔在内部运行一个计时器,每次间隔过去时,我都会检查注册的回调,看看是否是时候调用它们了,如果是的话。这很简单,但缺点是您只能获得计时器的“分辨率”。假设计时器设置为每秒滴答一次,并且您注册了一个要在半秒内调用的回调,它仍然可能不会在一秒钟内被调用。

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

4

5 回答 5

2

这是一个很好的方法。您应该动态设置计时器,使其在下一个事件发生时立即关闭。您可以通过将作业放入优先级队列中来做到这一点。毕竟,在任何情况下,您总是受限于系统可以提供的分辨率,但您应该编写代码,使其成为唯一的限制因素。

于 2009-02-01T20:04:29.213 回答
1

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

<关于 Windows 不是实时操作系统的标准免责声明,因此它的计时器必须总是有点不准确>

于 2009-02-01T20:05:22.363 回答
1

您只需要调度程序在列表中最早的项目到期时唤醒并执行某些操作。之后,您设置计时器以在下次唤醒调度程序。

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

于 2009-02-01T20:05:36.200 回答
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();
        }
    }
}
于 2009-02-01T20:09:10.657 回答
0

Quartz.Net作业调度程序。但是,这会安排课程而不是代表。

于 2010-12-06T22:26:23.267 回答