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

スケジューラを実装するために私が思いつく最善の方法は、特定の間隔で内部でタイマーを実行することです。間隔が経過するたびに、登録されたコールバックをチェックし、コールする時が来たかどうかを確認します。これは非常に単純ですが、タイマーの「解像度」しか得られないという欠点があります。タイマーが 1 秒に 1 回作動するように設定されていて、0.5 秒で呼び出されるようにコールバックを登録するとします。

これを解決するより良い方法はありますか?

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

Quartz.Netジョブ スケジューラ。ただし、これはデリゲートではなくクラスをスケジュールします。

于 2010-12-06T22:26:23.267 に答える
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 に答える