Почему событие "Истекший таймер" никогда не запускается?
У меня есть этот код в службе 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 (и вызывался метод, который не должен был быть, что приводило к его сбою и сбою службы). Поэтому я украсил Main() в Program.cs как "[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(), и каждый раз, когда она, как было задумано, возвращалась.
1 ответ
Как сказал Hans Passant в комментариях, в режиме отладки ваш код будет завершен сразу после вызова ConfigureService
так что нет времени на timer
быть выполненным.
В режиме релиза ServiceBase.Run
блокирует поток до тех пор, пока служба не завершит работу, но в отладочной версии этого не происходит.
РЕДАКТИРОВАТЬ:
На самом деле я пытался с Console.ReadLine()
и не остановился, по-видимому, стандартный ввод перенаправлен, просто попробуйте сохранить процесс, с бесконечным циклом или что-то.
Как это:
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();
while (true)
Thread.Sleep(100);
#endif
}