これはどのように行うのが最善ですか?サーバー上で実行されているアプリで、毎晩 03:00 にイベントをトリガーする必要があります。
12 に答える
Windows タスク スケジューラを使用する
(タスク スケジューラを使用する代わりに) アプリ コードを実行してこれを行う場合は、かなり長い (1 時間または 3,600 秒など) アプリをスリープさせる期間を選択する必要があります。アプリがループし、各スリープ コールの有効期限が切れるたびに、アプリは締め切り時刻 (03:00) までの残り時間を定期的にチェックします。残りのスリープ時間が粗い間隔の時間を下回ったら、短い間隔に減らします (毎回半分にするか、10 秒に減らします)。ターゲットの締切時刻に達するまで、スリープしてインターバル時間を短縮するループを続けます。
これにより、ループが頻繁にウェイクアップするのを防ぎます (86,400 の 1 秒間隔はやり過ぎです) が、スリープ時間が長すぎてアプリ ループが目標のデッドライン時間をオーバーシュートするのも防ぎます。
1秒間隔でタイマーを作成し、タイマーが切れたら3時かどうかを確認します。
ここには2つの基本的なオプションがあります。
既存のサービス内でこれを実行しようとしている場合は、タイマーを使用して毎晩3:00にトリガーし、「タスク」を実行できます。
そうは言っても、これは通常、Windowsタスクスケジューラを介してより適切に処理されます。アプリケーションを24時間年中無休で稼働させる代わりに、毎日3:00に実行するようにスケジュールするだけです。
編集:
コード(別のコメントに記載)からタスクスケジューラを操作する必要がある場合は、それも可能です。タスクスケジューラは、タスクスケジューラ(ITaskScheduler)を介して個々のタスク(ITask)を設定するためのAPIを提供します。
ただし、XP Embeddedで作業している場合は、通常のシステム構成機能を使用し、タスクを1日1回実行するように設定することをお勧めします。組み込みシステムでは、これを行うために、展開中に十分な制御が必要です。
マシンにログインしている人がいない場合でも確実に実行されるようにするには、サービスに組み込む必要があります。その後、トリガーが確実に発生するようにするためのさまざまな方法があります。
と次の3:00の差に設定されているSystem.Timers.Timer
場所を作成することを検討してください。Interval
DateTime.Now
これは、テーブルを監視するために 60 秒ごとにタイマーを実行する、私たちが書いたサービスの簡略化されたバージョンです...タイマーの経過イベントを変更して、時間を確認してから実行することができます。
Dim Timer As System.Timers.Timer
Protected Overrides Sub OnStart(ByVal args() As String)
Timer = New System.Timers.Timer(60000)
AddHandler Timer.Elapsed, AddressOf timer_Elapsed
Timer.Start()
End Sub
Protected Overrides Sub OnStop()
Timer2.Stop()
End Sub
Private Sub timer_Elapsed(ByVal pSender As Object, ByVal pargs As System.Timers.ElapsedEventArgs)
'Ensure the tick happens in the middle of the minute
If DateTime.Now.Second < 25 Then
Timer.Interval = 65000
ElseIf DateTime.Now.Second > 35 Then
Timer.Interval = 55000
ElseIf DateTime.Now.Second >= 25 And DateTime.Now.Second <= 35 Then
Timer.Interval = 60000
End If
'Logic goes here
End Sub
明らかに、可能であれば、ここで他の誰もが言及したようにタスクスケジューラを使用してください. これは、これを行うための推奨される方法です。たまたまこのコードが横たわっていたので、役に立つかもしれないので投稿したいと思いました. また、外部ソースがいつテーブルを編集するか分からなかったので、このコードはうまくいきました。md5sum で指摘されているように、間隔を正しいミリ秒数に設定すると、これを行うより効率的な方法になります。
この答えは少し左翼分野かもしれませんが、スケジュールされたタスクの一部にCruiseControl.NETをよく使用します。すべての人にとって完璧というわけではありませんが、毎晩実行したい大きな仕事で、他のコードや結果がそれに依存している場合は、良い選択です。いつでも実行するようにスケジュールし、機能した場合や失敗した場合にメールを受け取ることができます。他のスクリプト/コードが機能しない場合は実行し、開始前と開始後に必要なファイルをクリーンアップします。
すべての状況に対する完璧な解決策ではありませんが、それを必要とする人にとっては非常に強力です. 私たちはいくつかのビッグデータ処理ジョブにそれを使用しており、それが機能したか失敗したかをすべてメールで送信し、最初に失敗した場合は 30 分後に再試行します。それはあなたに素敵なファジー感を与えます:)
それはあなたがあなたに利用できるものに依存します。
Linux / Unix / Mac OS X、Windowsのタスクスケジューラ、または新しいバージョンのMac OS Xで起動している場合は、 cronジョブを使用するのが最善の策です。
アプリケーション内からこれを実行する場合は、定期的に時刻をチェックし、03:00の場合はイベントを発生させるループが必要になりますが、これは理想的ではありません。
Windows タスク スケジューラ (klausbyskov の提案による) または SQL Server ジョブ。
編集:
または、動的に割り当てられた時間が必要な場合は、10 分ごとにポーリングし、目的の時間に何らかのアクションを実行する Windows サービスを作成できます。
C# で Windows サーバーを作成するのはかなり簡単で、これを行うことができます。実行中 (または実行中でない) に何が起こっているのかを判断するのは非常に難しいため、セキュリティとログを把握していることを確認してください。
プログラムはコマンドラインから実行できますか? その場合は、foo.bat ファイルを作成し、プログラムのコマンド ラインを呼び出します (非常に簡単です)。
次に、タスク スケジューラを使用して、毎日午前 3 時に .bat ファイルを実行します。
System.Threading.Timerを使用します。
スケジュールされたタスクを実行するために、ASP.NET アプリケーションでスレッドを生成しています。