待機可能なタイマー、間隔ごとに実行していますか?

.net .net-4.0 c# multithreading timer
待機可能なタイマー、間隔ごとに実行していますか?

C#、. NET Framework 4.0を使用します。 20分、30分、45分に設定された3つのTimeSpanオブジェクトがあります。 タイマーが実際に起動するタイミングに関係なく、正確な分間隔でのみタイマーを実行したい。 タイマーの発火を次のようにする必要があります(1時間ごと)。

timerA 1:00
timerB 1:00
timerA 1:20
timerB 1:30
timerA 1:40
timerC 1:45
timerA 2:00
timerB 2:00
timerA 2:20
timerB 2:30
timerA 2:40
timerC 2:45

Waitableタイマーは正しい動きだと思いましたが、簡単な例がないため、そうではないと思います。 この機能を取得するための最良の方法は何ですか(可能な場合はクロックドリフトを回避したいのですが、今は何かに必死です)。 私はWaitableと結婚していません。 timerCは1時間に1回しか実行されないことも理解していますが、これは毎時45分にのみ実行されるように設定されているため問題ありません。

注-Quartz.NETを使用する準備ができていません。

ありがとう。

  1  0


ベストアンサー

私が得ることができる最も近いものは、待機時間を使用してターゲット時間を「クリープアップ」することです(sleep()、タイムアウト付きイベント、スレッドタイマーまたは古典的な「メインスレッドウィンドウタイマー」、ミリ秒の半分の数に設定「現在」およびリアルタイムクロックから計算されたターゲット時間。 残りのmsが何らかの制限(500など)よりも大きい場合、残りのmsを再計算して、再度待機します。 残りのmsが制限より低い場合、ターゲットに到達するかそれを超えるまでリアルタイムクロックのループを開始し、TimeSpanオブジェクトのtimeout()メソッドを呼び出します。

TimeSpanオブジェクトをタイムアウト時間順に並べられたキューに入れて、待機可能オブジェクトを1つだけ必要とすることができます。 これは、ターゲット時間が近づくとループするスレッドが1つしかないため、TimeSpanイベントが「同時に」発生することが多い場合に、より正確になる可能性があります。

Rgds、マーティン

1


私はこれがあなたのために仕事をすると思う:

static void Main(string[] args)
{
    StartTimer(TimeSpan.FromMinutes(20.0), "TimerA", true);
    StartTimer(TimeSpan.FromMinutes(30.0), "TimerB", true);
    StartTimer(TimeSpan.FromMinutes(45.0), "TimerC", true);

    Console.WriteLine("Press any key to exit...");
    Console.ReadLine();
}

タイマー開始関数はタイマーを開始し、それを返します(参照が必要な場合)。 ここで重要なのは、タイマー名を付けて、タイマーを1時間に合わせたいかどうかを伝えることです。 1時間に合わせたくない場合は、指定した頻度でタイマーがすぐに開始されます。

public static Timer StartTimer(TimeSpan frequency, string timerName, bool alignToHour)
{
    if (alignToHour)
    {
        return new Timer(OnTimerTick, timerName, ComputeDelay(frequency), frequency);
    }
    else
    {
        return new Timer(OnTimerTick, timerName, TimeSpan.Zero, frequency);
    }
}

タイマーが作動すると起動される関数。

public static void OnTimerTick(object state)
{
    Console.WriteLine((string)state + " " + DateTime.Now.ToString("H:mm"));
}

このメソッドは、1時間にタイマーを調整する必要がある場合に必要な遅延を計算します。 頻度が1時間未満または1分以上の場合にのみ機能します。

public static TimeSpan ComputeDelay(TimeSpan frequency)
{
    if (frequency > TimeSpan.FromHours(1.0) ||
        frequency < TimeSpan.FromMinutes(1.0))
    {
        throw new ArgumentException(
            "The frequency cannot be more than one hour or less than one minute!");
    }

    return frequency - TimeSpan.FromMinutes(DateTime.Now.Minute % frequency.Minutes);
}

*注:*この例では、1時間間隔で45分タイマーを実行しますが、20分間隔と30分間隔でそれぞれ20分タイマーと30分タイマーを実行します。 私のコードは、1時間の頻度で45分のタイマーでは機能しませんが、それぞれの頻度で20、30、および45分のタイマーで機能します。 あなたの例が間違っているかどうかはわかりませんが、間違っていなければ、ここからその違いに対処する方法を理解できるはずです。

1


タイトルとURLをコピーしました