ScheduleServiceクラスの実装
System.Web.Caching.Cacheクラスとコールバック関数
ASP.NETのCache
オブジェクトにはデータをキャッシュすることが可能ですが、キャッシュを更新する際に有効期限を指定してデータをキャッシュさせることが可能です。また有効期限が切れたときにある関数を実行させることができます。このコールバックメソッド内で、再度有効期限付き&コールバックメソッドの登録を行うことで、定期的に関数を実行するということが可能になります。
添付したサンプルコードはジョブの実行の部分も混在しているので、分かりやすいようにコールバックメソッドの再登録の部分だけを以下に示します。
public static void Start() { ScheduleService.RegisterTickFunction(); } private static void RegisterTickFunction() { ScheduleService.zCache.Insert( ScheduleService.zSingleton.CacheKey, "ScheduleService", null, DateTime.MaxValue, TimeSpan.FromMinutes(1), CacheItemPriority.Normal, new CacheItemRemovedCallback(ScheduleService.Tick)); } private static void Tick(String inKey, Object inValue, CacheItemRemovedReason inReason) { ScheduleService.RegisterTickFunction(); }
サービスを開始するには以下のように記述します。サンプルソースでは「Global.cs」に記述してあります。
void Main()
{
ScheduleService.Start();
}
これにより関数がキャッシュオブジェクトに登録されます。
1分後に有効期限が切れると、コールバックメソッドTick
が実行され、Tick
メソッド内でキャッシュオブジェクトの登録が行われます。結果、1分ごとに定期的に処理が実行されるようになります。
HttpApplicationクラス
「Global.asax」ファイルの実態はHttpApplication
クラスの継承したクラスです。
「Global.asax」中にインラインで記述しても良いのですが、そうすると開発環境での動作がちょっと遅いので私は別ファイルに記述するようにしています。「Global.asax」で
<%@ Application Language="C#" CodeBehind="~/App_Code/Global.cs" Inherits="Higuchi.WindowsServiceSample.Biz.Global" %>
と記述することにより、任意のクラスを指定できます。CodeBehind
は物理ファイルの位置、Inherits
は名前空間を含むクラスの名前を指定します。このようにすることで、アプリケーション全体でのログの取得やセキュリティの認証などの処理を実装しやすくなります。
シングルトンパターンの実装
ScheduleService
クラスは複数のインスタンスである必要はないので、シングルトンパターンで実装します。シングルトンパターンとはアプリケーション全体で、インスタンスが1つしか生成しないようににするためのデザインパターンです。ポイントは、
- 自分自身への参照を保持するstaticな変数
- コンストラクタをprivateにする
- 唯一のインスタンスへのアクセスを提供するstaticなプロパティの実装
となります。
マルチスレッドの考慮
Webアプリケーションは複数のリクエストがマルチスレッドで実行されます。static変数へのアクセスは適切にlockをかけないと再現性の低い不具合が埋め込まれ、原因の特定が困難になります。
lockをかけるべき部分は、Start
メソッドで最初にコールバック関数を登録する部分と、登録されたジョブを実行する部分にかけるとなります。lockステートメントにより、複数のスレッドが同時にアクセスしたとしても、1つのスレッドのみが該当部分を実行することを保証できます。
複数サイトでの利用
この機能を利用する際、複数のWebサイトをたててスケールアウトするような場合では、少し工夫が必要です。
例えば定期的にDBサーバの不要なデータを削除する処理を実行しているとします。それぞれのWebサイトでDBに対して削除処理をするのは無駄なので、どれか1つのサイトのみ実行するようにコードを書き換えたりする必要が出てくるでしょう。
解決策として、「Web.Config」ファイルなどにサービスを有効にするかどうかを設定できるように機能拡張します。そして複数あるサイトのうち1つのサイトのみサービスが実行されるように設定ファイルを構成します。詳細はサンプルには入っていませんが、ヒントとして参考にしてみてください。
まとめ
ASP.NETにWindowsServiceのような機能を実装することで、設定の手間などを低減できます。
このクラスを利用すれば、指定した時刻にメールを送ったり、毎日1回古いデータを削除したり、1時間ごとに新しい情報がないかチェックしたりなどの機能を簡単に作成できるでしょう。
参考になれば幸いです。