次のような動作のタイマーを作成します。
タスク/ジョブの処理時間がタイマー間隔未満の場合、(timer.interval - ジョブ/ジョブの処理時間) でタイマーを開始します
ジョブ/タスクの処理時間がタイマー間隔を超えている場合は、次のジョブ/タスクをすぐに開始します
以下のコードは機能しますが、ElapsedEventHandler メソッドでジョブ/タスクを最初に実行してから、新しいタイマー間隔を設定できる理由を知りたいです。間隔が経過すると、System.Timers.Timer の Elapsed イベントが発生します。オプション AutoReset = false を使用して、最初の Interval が経過した後、Timer が Elapsed イベントを 1 回だけ発生させるように設定します。その後、Timer.Start() を手動で呼び出して、再度開始する必要があります。
using System;
using System.Timers;
namespace TestTimer
{
class Program
{
private static Timer t;
private static double intervalMiliseconds;
static void Main(string[] args)
{
intervalMiliseconds = 5000; // 5 seconds
t = new Timer();
t.Interval = intervalMiliseconds;
t.AutoReset = false;
t.Elapsed += new ElapsedEventHandler(OnTimedEvent);
t.Start();
log("Timer started at " + DateTime.Now.ToString());
log("Interval is: " + defaultIntervalMiliseconds);
Console.ReadKey();
}
private static void log(string text)
{
Console.WriteLine(text + "\n");
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// if t.Interval is set here thread just kills the job if it
// runs longer than interval
t.Interval = intervalMiliseconds;
log("ElapsedEvent triggered at " + DateTime.Now.ToString());
// job
DateTime startTime = DateTime.Now;
log("job started" );
System.Threading.Thread.Sleep(8000); // 8 sec
log("job ended" );
TimeSpan jobTime = DateTime.Now.Subtract(startTime);
log("job took " + jobTime.TotalSeconds + " seconds");
// if we set t.Interval here it works so first the job
// must be done and than we can set timer interval ? why ?
//t.Interval = intervalMiliseconds;
if (jobTime.TotalMilliseconds < t.Interval)
{
t.Interval = t.Interval - jobTime.TotalMilliseconds;
log("Job ended Earlier starting Event in: " + t.Interval);
}
else
{
t.Interval = 100;
log("Job overpass interval. Current time: " +
DateTime.Now.ToString());
}
t.AutoReset = false;
t.Start();
}
}
}
この結果:
メソッド OnTimedEvent の開始時に t.Interval をコメントし、ジョブが完了した後に t.Interval のコメントを外すと、すべてが機能します。この結果:
メソッド OnTimedEvent の開始時にタイマー間隔を設定できないのはなぜですか。タスク/ジョブがタイマー間隔よりも長く実行された場合、スレッドは単にジョブを強制終了します。誰かが何かアイデアを持っていれば、本当に感謝していますか? これは、スレッドとメインスレッド(タイマーが実行される)の同期と関係がありますか? メソッド OnTimedEvent を呼び出すと、タイマーは AutoReset = false であるため、そのメソッドを再度呼び出すことはありません。タイマーのプロパティを設定すると、どのような違いが生じるでしょうか?