Windows サービスに次のコードがあります。
public void ConfigureService()
{
//timer = new Timer { Interval = 600000 };
timer = new Timer { Interval = 10000 };
// 10 minutes; 1 second while testing
timer.Elapsed += timer_Tick;
timer.Enabled = true;
RoboRprtrLib.WriteToLog("RoboRprtrService has started");
}
private void timer_Tick(object sender, ElapsedEventArgs eeargs)
{
timer.Elapsed -= timer_Tick;
try
{
RoboRprtrLib.WriteToLog("Timer has ticked");
RoboRprtrLib.GenerateAndEmailDueReports();
}
finally
{
timer.Elapsed += timer_Tick;
}
}
ConfigureService() は Program.cs から呼び出されます。
static void Main()
{
// got this idea ("How to Debug or Test your Windows Service Without Installing it...") from http://www.codeproject.com/Tips/261190/How-to-Debug-or-Test-your-Windows-Service-Without
#if(!DEBUG)
var ServicesToRun = new ServiceBase[]
{
new RoboRprtrService()
};
ServiceBase.Run(ServicesToRun);
#else
var rrs = new RoboRprtrService();
rrs.ConfigureService();
#endif
}
次の行の ConfigureService() にブレークポイントがあります。
timer = new Timer { Interval = 10000 };
到達しました。ConfigureService() メソッド全体をステップ実行できます。
最初の行の Elapsed/Tick イベントにブレークポイントがあります。
timer.Elapsed -= timer_Tick;
...そして、到達することはありません。
なぜだめですか?タイマーが 10 秒後にトリップするように設定されていませんか? その時点で Tick イベント ハンドラーを呼び出す必要がありますか?
アップデート
これは、ServiceBase から派生するクラスのコード全体です。
public partial class RoboRprtrService : ServiceBase
{
private Timer timer;
public RoboRprtrService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
ConfigureService();
}
public void ConfigureService()
{
//timer = new Timer { Interval = 600000 };
timer = new Timer { Interval = 50000 };
// 10 minutes; 50 seconds while testing
timer.Elapsed += timer_Tick;
timer.Enabled = true;
RoboRprtrLib.WriteToLog("RoboRprtrService has started");
}
private void timer_Tick(object sender, ElapsedEventArgs eeargs)
{
timer.Elapsed -= timer_Tick;
try
{
RoboRprtrLib.WriteToLog("Timer has ticked");
RoboRprtrLib.GenerateAndEmailDueReports();
}
finally
{
timer.Elapsed += timer_Tick;
}
}
protected override void OnStop()
{
timer.Enabled = false;
RoboRprtrLib.WriteToLog("RoboRprtrService has stopped");
}
}
更新 2
私には奇妙に思えますが、次の行を追加すると:
RoboRprtrLib.GenerateAndEmailDueReports();
... ConfigureService() メソッドの最後まで、タイマーは最終的に作動します。
更新 3
さらに奇妙な点: STAThread 属性を追加する必要があるというエラー メッセージが表示されました (そして、呼び出してはならないメソッドが呼び出されたため、メソッドが失敗し、サービスがクラッシュしました)。そのため、Program.cs の Main() を "[STAThread]" で装飾したところ、正常に動作するようになりました。
操作中にタイマーが数回トリップしましたが、処理が発生している場合に終了するコードがあります。呼び出されたメソッドが完了すると、IDE が「ふーふっ! ここから出てきた!」と言うかのように「フラッシュ」しました。
したがって、私の Program.cs コードは次のようになります。
[STAThread]
static void Main()
{
#if(!DEBUG)
var ServicesToRun = new ServiceBase[]
{
new RoboRprtrService()
};
ServiceBase.Run(ServicesToRun);
#else
var rrs = new RoboRprtrService();
rrs.ConfigureService();
Console.ReadLine();
#endif
}
...そして、ServiceBase から派生するクラスで最も適切なコードは次のとおりです。
public void ConfigureService()
{
//timer = new Timer { Interval = 600000 };
timer = new Timer { Interval = 50000 };
// 10 minutes; 50 seconds while testing
timer.Elapsed += timer_Tick;
timer.Enabled = true;
RoboRprtrLib.WriteToLog("RoboRprtrService has started");
operationIsRunning = true;
RoboRprtrLib.GenerateAndEmailDueReports();
operationIsRunning = false;
}
private void timer_Tick(object sender, ElapsedEventArgs eeargs)
{
if (operationIsRunning) return;
operationIsRunning = true;
. . .
「if (operationIsRunning) return;」GenerateAndEmailDueReports() の実行中に、前回の実行中に tick ハンドラーのブレークポイントに 3 回到達し、そのたびに設計どおりに戻りました。