1

毎日午前9時に実行することになっているルーチンがあります。

protected override void OnStart(string[] args)
{
   log.Info("Info - Service Start");
   string timeToRunStr = "09:00";
   var timeStrArray = timeToRunStr.Split(';');
   foreach (var strTime in timeStrArray)
   {
        timeToRun.Add(TimeSpan.Parse(strTime));
   }
    ResetTimer();
}

void ResetTimer()
{
   log.Info("Info - Reset Timer");
   try
   {
       TimeSpan currentTime = DateTime.Now.TimeOfDay;
       TimeSpan nextRunTime = timeToRun[0];
       foreach (TimeSpan runTime in timeToRun)
       {
           if (currentTime < runTime)
           {
               nextRunTime = runTime;
               // log.Info("Info - in loop");
               _timer = new Timer((nextRunTime - currentTime).TotalSeconds * 1000);
               break;
           }
           else {
             TimeSpan test = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 16, 51, 0).AddDays(1).Subtract(DateTime.Now);
             nextRunTime = test;
              _timer = new Timer((nextRunTime).TotalSeconds * 1000);
            }
        }               
        log.Info("Info - Timer : " + (nextRunTime - currentTime).TotalSeconds * 1000);
        log.Info("Info - nextRuntime : " + nextRunTime);
        log.Info("Info - currentTime : " + currentTime);
        _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        _timer.Start();
    }
    catch (Exception ex)
    {
        log.Error("This is my timer error - ", ex);
    }
}

午前9時に実行され、次の実行時間には1.09:00:00と表示されます。これは、明日の午前9時を意味しますか?

4

2 に答える 2

7

1.09:00:00は、1日9時間の期間を意味します

于 2012-06-20T08:02:58.170 に答える
4

MSDNドキュメントから:

TimeSpan値は、[-] d.hh:mm:ss.ffとして表すことができます。ここで、オプションのマイナス記号は負の時間間隔を示し、dコンポーネントは日数、hhは24時間制で測定した時間数mmです。は分、ssは秒、ffは秒の何分の1かです。つまり、時間間隔は、時刻のない正または負の日数、時刻のある日数、または時刻のみで構成されます。

あなたの例では、TimeSpanは1日、9時間、0分、0秒です。

あなたの実際の質問に答えて:

午前9時に実行され、次の実行時間には1.09:00:00と表示されます。これは、明日の午前9時を意味しますか?

状況によって異なります。現在の時間にタイムスパンを追加すると(つまり、現在のバッチが終了したとき)、次の日の午後6時頃の時間が得られます。DateTime.Now.Date(指定された日付の真夜中)を取得し、それにタイムスパンを追加して、翌日の午前9時を取得する必要があります。

ただし、精度と回復の要件によっては、使いやすい(または少なくともコードを読む)ことができるスケジューリング コンポーネントがたくさんあります。

元の方法では、次のようにする方が簡単な場合があります。

protected override void OnStart(string[] args)
{
   log.Info("Info - Service Start");
   DateTime startTime = DateTime.Date.AddHours(9); //9AM Today
   timeToRun.Add(startTime); 
   CreateTimer();
}

void CreateTimer()
{
   log.Info("Info - Reset Timer");
   try
   {
      if(_timer == null){
         _timer = new Timer(3600 * 1000); //once an hour
         _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
         _timer.Start();
      }
    }
    catch (Exception ex)
    {
        log.Error("This is my timer error - ", ex);
    }
}

次に、timer_elapsedイベントで、次の操作を行います(イベントの署名を失礼します。これは、メモリからのものです)。

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
   if(DateTime.Now > timeToRun[0])
   {
      //Code to run the job
      //Then we reset the timer - can do this here or at the end of the job code
      timeToRun[0] = DateTime.Date.AddDays(1).AddHours(9); //9AM tomorrow.
    }

 }

リセットタイマーは複雑すぎます。すべてのコードは必要ありません。タイマーを作成し、1時間ごとにチェックしてもらい、時間がジョブの実行時間よりも長い場合は、ジョブを実行し、次の実行時間を明日の午前9時に移動します。このような単純なタイマーを作成するために必要なのはこれだけです。

このアプローチの問題には、きめ細かいものではないという事実が含まれます。仕事は午前9時に開始されない可能性があるため、それが重要な場合は、前述のリンクされたスケジューリングライブラリの1つを調査することをお勧めします

于 2012-06-20T08:18:08.093 に答える