1

我在 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;
    }
}

从 Program.cs 调用 ConfigureService():

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 中用“[STAThread]”装饰了 Main(),现在它可以正常工作了。

计时器在操作过程中触发了几次,但如果正在处理,我有代码退出。当被调用的方法完成时,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;
    . . .

“如果(操作IsRunning)返回;” 在 GenerateAndEmailDueReports() 执行期间,在我上次运行期间,滴答处理程序中的断点达到了 3 次,并且每次都按设计返回。

4

1 回答 1

2

正如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
}
于 2016-05-24T17:03:47.670 回答