请参阅下面的文件 Service.cs 和 Program.cs 以及 事件日志...
我注意到当项目的属性 Output Type 设置为 Windows Application 时,System.Timers.Timer 在 Windows 服务中无法正常工作。但是,当项目的属性 Output Type 设置为 Console Application 时,它确实有效。
最快最简单的解决方案是将项目的属性输出类型设置为Console Application。当项目的属性 输出类型 设置为 Windows Application 时,控制台语句将被忽略。没有代码更改...只是项目设置更改。
在随后的回复中,我将提交一个替代解决方案,其中 System.Timers.Timer 将在 Windows 服务中按预期运行。它涉及添加“未记录”的代码。
为了了解发生了什么,我添加了三个断点(断点 1、断点 2 和断点 3)。断点 1 和 2 在下面的 Service.cs 中,断点 3 在下面的 Program.cs 中(参见代码中的注释:“// Breakpoint...”)。我运行了 Windows 服务,项目的属性 输出类型 设置为 Windows Application 并记录了所有结果(请参阅下面的事件日志)。
我们看到如下(见Service.cs中的internal void TestStartupAndStop(string[] args)方法):OnStart事件触发OnStart 方法,其中定时器初始化成功(即不抛出异常)。 OnStop 事件触发 OnStop 方法,其中对象被成功地正确处理(即,不抛出异常)。但是随后,发生了完全出乎意料的事情...OnTimer 事件触发了 OnTimer 方法,其中任务成功执行了两次(即,没有抛出异常)之后服务已停止!
?(疯了!)
文件:Service.cs
using System.Timers;
namespace <namespace>
{
public partial class Service : ServiceBase
{
protected void OnTimer(object sender, ElapsedEventArgs e)
{
var methodName = "protected void OnTimer(object sender, ElapsedEventArgs e)";
try
{
EventLogWriteEntry("Running Service...");
EventLogWriteEntry("Do Task...");
// :
// :
// :
EventLogWriteEntry("Task Done...");
EventLogWriteEntry("Service ran successfully.");
}
catch (Exception ex)
{
var errorMessage = "Error running Service...";
HandleGeneralException(errorMessage, ex, methodName);
}
}
protected override void OnStart(string[] args)
{
var methodName = "protected override void OnStart(string[] args)";
try
{
EventLogWriteEntry("Starting Service...");
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = double.Parse(ConfigurationManager.AppSettings["Timer.Interval"]); // Set Interval to 5 seconds
timer.Elapsed += new ElapsedEventHandler(OnTimer);
//timer.Enabled = true; // timer.Start() does the same exact thing
timer.Start();
EventLogWriteEntry("Service started successfully.");
}
catch (Exception ex)
{
var errorMessage = "Error starting Service...";
HandleGeneralException(errorMessage, ex, methodName);
}
}
protected override void OnStop()
{
var methodName = "protected override void OnStop()";
try
{
EventLogWriteEntry("Stopping Service...");
EventLogWriteEntry("Do Clean-Up...");
// :
// :
// :
EventLogWriteEntry("Clean-Up Done...");
EventLogWriteEntry("Service stopped successfully.");
}
catch (Exception ex)
{
var errorMessage = "Error stopping Service...";
HandleGeneralException(errorMessage, ex, methodName);
}
}
// Note: Set project's property Output Type to Console Application. Revert to Windows Application when done.
// See comment in static void Main() in Program.cs
internal void TestStartupAndStop(string[] args) // FOR TESTING PURPOSES ONLY!
{
this.OnStart(args);
Console.WriteLine("Press ENTER to stop..."); // Console statements are ignored when Output Type is set to Windows Application.
Console.ReadLine();
this.OnStop(); // Breakpoint 1: Wait 60 seconds...
} // Breakpoint 2: Wait 60 seconds...
}
}
文件:Program.cs
namespace <namespace>
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
// Note: The If block is for testing interactively.
// The Else block is the normal execution block of code.
// No need to comment/uncomment code.
// See comment in internal void TestStartupAndStop(string[] args) in Service.cs
if (Environment.UserInteractive) // FOR TESTING PURPOSES ONLY!
{
var service = new Service();
service.TestStartupAndStop(null);
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service()
};
ServiceBase.Run(ServicesToRun);
}
} // Breakpoint 3: Wait 60 seconds... Timer events fired AFTER here!
}
}
事件日志
| Level |
Date and Time |
Source |
Event ID |
Task Category |
Message |
| Breakpoint 1: Wait 60 seconds... |
|
|
|
|
|
| Information |
5/31/2021 7:24 |
ServiceEventSource |
0 |
None |
Starting Service... |
| Information |
5/31/2021 7:24 |
ServiceEventSource |
0 |
None |
Initialize timer... |
| Information |
5/31/2021 7:24 |
ServiceEventSource |
0 |
None |
Service started successfully. |
| Breakpoint 2: Wait 60 seconds... |
|
|
|
|
|
| Information |
5/31/2021 7:25 |
ServiceEventSource |
0 |
None |
Stopping Service... |
| Information |
5/31/2021 7:25 |
ServiceEventSource |
0 |
None |
Do Clean-Up... |
| Information |
5/31/2021 7:25 |
ServiceEventSource |
0 |
None |
Clean-Up Done... |
| Information |
5/31/2021 7:25 |
ServiceEventSource |
0 |
None |
Service stopped successfully. |
| Breakpoint 3: Wait 60 seconds... Timer events fired AFTER here! |
|
|
|
|
|
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Running Service... |
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Do Task... |
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Task Done... |
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Service ran successfully. |
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Running Service... |
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Do Task... |
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Task Done... |
| Information |
5/31/2021 7:27 |
ServiceEventSource |
0 |
None |
Service ran successfully. |