简体   繁体   English

为什么计时器的已逝事件从不触发?

[英]Why is my Timer's Elapsed event never being fired?

I've got this code in a Windows Service: 我在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() is called from Program.cs: 从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
}

I have a breakpoint in ConfigureService() on this line: 我在此行的ConfigureService()中有一个断点:

timer = new Timer { Interval = 10000 };

It is reached; 达到了; I can step through the entire ConfigureService() method. 我可以逐步完成整个ConfigureService()方法。

I have a breakpoint in the Elapsed/Tick event on the first line: 我在第一行的Elapsed / Tick事件中有一个断点:

timer.Elapsed -= timer_Tick;

...and it is never reached. ...而且永远都无法达到。

Why not? 为什么不? Isn't the timer set to trip after 10 seconds, at which point the Tick event handler should be called? 计时器是否没有设置为在10秒后跳闸,此时应调用Tick事件处理程序?

UPDATE 更新

This is the entire code for the class deriving from ServiceBase: 这是从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");
    }

}

UPDATE 2 更新2

It seems odd to me, but if I add this line: 对我来说似乎很奇怪,但是如果我添加这一行:

RoboRprtrLib.GenerateAndEmailDueReports();

...to the end of the ConfigureService() method, the timer is eventually tripped. ...到ConfigureService()方法的结束时,定时器最终跳闸。

UPDATE 3 更新3

More oddities: I was getting err msgs about needing to add the STAThread attribute (and a method was being called that shouldn't have been, which caused it to fail and the service to crash). 更加奇怪的是:我收到了有关需要添加STAThread属性的错误信息(并且正在调用一个本不应该被调用的方法,这会导致它失败并导致服务崩溃)。 So I decorated Main() in Program.cs with "[STAThread]" and now it works as it should. 因此,我用“ [STAThread]”修饰了Program.cs中的Main(),现在它可以正常工作了。

The timer tripped several times during the operation, but I have code to exit if processing is occurring. 计时器在操作过程中跳了几次,但如果有处理,我有代码要退出。 When the called method completed, the IDE "flashed" as if to say, "Poof! I'm outta here!" 当调用的方法完成时,IDE“闪烁”,好像在说:“ Po!我不在这里!”

So my Program.cs code is now: 所以我的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
}

...and the most pertinent code in the class that derives from ServiceBase is: ...并且从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;
    . . .

The "if (operationIsRunning) return;" “ if(operationIsRunning)返回;” breakpoint in the tick handler was reached three times during my last run while GenerateAndEmailDueReports() was executing, and each time it, as designed, returned. 在我的上一次运行期间,GenerateAndEmailDueReports()正在执行时,滴答处理程序中的断点已达到3次,并且每次按设计返回时,都达到了该断点。

As Hans Passant said in comments, in debug mode you code will terminate immediately after calling ConfigureService , so there is no time for the timer to be executed. 正如Hans Passant在评论中所说,在调试模式下,代码将在调用ConfigureService之后立即终止,因此没有时间执行timer

In release mode ServiceBase.Run blocks the thread until the service has finished, but this doesn't happen in debug version. 在发布模式下, ServiceBase.Run阻塞线程,直到服务完成为止,但这在调试版本中不会发生。

EDIT : 编辑

Actually I tried with Console.ReadLine() and did not stop, apparently standard input is redirected, just try to keep the process running, with an infinite loop or something. 实际上,我尝试使用Console.ReadLine()并没有停止,显然标准输入被重定向了,只是尝试使进程运行,并进行无限循环或其他操作。

Like this: 像这样:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM