为什么我的 Timer's Elapsed 事件永远不会被触发?
Why is my Timer's Elapsed event never being fired?
我在 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 派生的 class 的完整代码:
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 属性的错误消息(并且调用了一个不应该调用的方法,这导致它失败并且服务崩溃)。所以我用“[STAThread]”装饰了 Program.cs 中的 Main(),现在它可以正常工作了。
定时器在操作过程中多次跳闸,但我有代码可以在处理过程中退出。当被调用的方法完成时,IDE "flashed" 就好像在说,"Poof! I'm outta here!"
所以我的 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 派生的 class 中最相关的代码是:
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;
. . .
在我上次 运行 执行 GenerateAndEmailDueReports() 期间,滴答处理程序中的 "if (operationIsRunning) return;" 断点达到了三次,并且每次都按设计返回。
正如 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
}
我在 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 派生的 class 的完整代码:
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 属性的错误消息(并且调用了一个不应该调用的方法,这导致它失败并且服务崩溃)。所以我用“[STAThread]”装饰了 Program.cs 中的 Main(),现在它可以正常工作了。
定时器在操作过程中多次跳闸,但我有代码可以在处理过程中退出。当被调用的方法完成时,IDE "flashed" 就好像在说,"Poof! I'm outta here!"
所以我的 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 派生的 class 中最相关的代码是:
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;
. . .
在我上次 运行 执行 GenerateAndEmailDueReports() 期间,滴答处理程序中的 "if (operationIsRunning) return;" 断点达到了三次,并且每次都按设计返回。
正如 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
}