Windows TaskScheduler を使用せずに、executeEveryDayMethod() を 1 日に 1 回実行する賢い方法はありますか?
10 に答える
私は次のことを行うことでこれを達成しました...
- 20 分ごとに起動するタイマーを設定します (実際のタイミングはあなた次第ですが、1 日に何度か実行する必要がありました)。
- Tick イベントごとに、システム時刻を確認します。メソッドのスケジュールされた実行時間と時間を比較します。
- 現在の時間がスケジュールされた時間よりも短い場合は、永続ストレージをチェックして、メソッドが最後に実行された日時の値を取得します。
- メソッドが 24 時間以上前に最後に実行された場合は、メソッドを実行し、この実行の日時をデータ ストアに隠しておきます
- メソッドが最後に 24 時間以内に実行された場合は、無視してください。
HTH
*編集 - C# のコード サンプル :: 注: 未テスト...
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Timer t1 = new Timer();
t1.Interval = (1000 * 60 * 20); // 20 minutes...
t1.Elapsed += new ElapsedEventHandler(t1_Elapsed);
t1.AutoReset = true;
t1.Start();
Console.ReadLine();
}
static void t1_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime scheduledRun = DateTime.Today.AddHours(3); // runs today at 3am.
System.IO.FileInfo lastTime = new System.IO.FileInfo(@"C:\lastRunTime.txt");
DateTime lastRan = lastTime.LastWriteTime;
if (DateTime.Now > scheduledRun)
{
TimeSpan sinceLastRun = DateTime.Now - lastRan;
if (sinceLastRun.Hours > 23)
{
doStuff();
// Don't forget to update the file modification date here!!!
}
}
}
static void doStuff()
{
Console.WriteLine("Running the method!");
}
}
}
quartz.netを見てください。.net用のスケジューリングライブラリです。
具体的にはこちらをご覧ください。
実行される時間が関係なく、プログラムが起動するたびにリセットできる場合は、タイマーを設定するだけで済みます。これが最も簡単な方法です。それが受け入れられない場合は、ここで提示されたソリューションのように、より複雑になり始めますが、それでも永続性の問題は解決されません。スケジュールされたタスクと同じことを本当にしたい場合は、個別に取り組む必要があります。完全に優れた既存の機能を複製するためにすべてのトラブルを経験する価値があるかどうか、もう一度検討したいと思います。
これは関連する質問です(そこから取られた例)。
using System;
using System.Timers;
public class Timer1
{
private static Timer aTimer = new System.Timers.Timer(24*60*60*1000);
public static void Main()
{
aTimer.Elapsed += new ElapsedEventHandler(ExecuteEveryDayMethod);
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void ExecuteEveryDayMethod(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
1 日 1 回、午後 7 時から午後 8 時の間にジョブを実行するには、間隔 = 3600000 ミリ秒のタイマーを設定し、タイマー ティックに対して次のコードを実行します。
private void timer1_Tick(object sender, EventArgs e)
{
//ensure that it is running between 7-8pm daily.
if (DateTime.Now.Hour == 19)
{
RunJob();
}
}
1時間のウィンドウは私にとっては問題ありません。時間の細分性を高めるには、タイマーの間隔を短くし (1 分間に 60000)、if に分を含める必要があります。
例えば
{
//ensure that it is running at 7:30pm daily.
if (DateTime.Now.Hour == 19 && DateTime.Now.Minute == 30)
{
RunJob();
}
}
アプリケーションを Windows サービスとして実行できるようにコンピューターを再起動すると、問題が発生する可能性があります。
時間を照会して、ある時間枠内であれば実行することができます。そうすれば、マシンがオフになった場合でも、メソッドを呼び出すか、Vinko の提案のようなタイマーを使用できます。
しかし、より良い解決策 (古い CRON バージョンに似ているため、実績のあるパターン) は永続的なデータを保持することです。過去 24 時間以内に変更されていない場合は、それに触れてメソッドを実行します。このようにして、たとえばアプリケーションが週末に外出している場合に、メソッドが最初に実行されるようにします。
以前にC#でこれを行ったことがありますが、1年前に別のジョブで行ったので、コードはありませんが、約20行(コメントなどを含む)程度でした。
1 日に 1 回だけ実行し、いつ実行するかを気にしない場合は、これでうまくいきます (真夜中過ぎに実行されます)。
DateTime
変数を宣言します。
DateTime _DateLastRun;
起動時に、最初の日付値を設定します。
_DateLastRun = DateTime.Now.Date;
アクションを実行するかどうかを確認するロジック領域で:
if (_DateLastRun < DateTime.Now.Date)
{
// Perform your action
_DateLastRun= DateTime.Now.Date;
}