views:

1600

answers:

9

I have a windows service written in c#. It has a timer inside, which fires some functions on a regular basis. So the skeleton of my service:

public partial class ArchiveService : ServiceBase
{
    Timer tickTack;
    int interval = 10;
    ...

    protected override void OnStart(string[] args)
    {
        tickTack = new Timer(1000 * interval);

        tickTack.Elapsed += new ElapsedEventHandler(tickTack_Elapsed);
        tickTack.Start();
    }

    protected override void OnStop()
    {            
        tickTack.Stop();
    }    

    private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
    {
        ...
    }
}

It works for some time (like 10-15 days) then it stops. I mean the service shows as running, but it does not do anything. I make some logging and the problem can be the timer, because after the interval it does not call the tickTack_Elapsed function.

I was thinking about rewrite it without a timer, using an endless loop, which stops the processing for the amount of time I set up. This is also not an elegant solution and I think it can have some side effects regarding memory.

The Timer is used from the System.Timers namespace, the environment is Windows 2003. I used this approach in two different services on different servers, but both is producing this behavior (this is why I thought that it is somehow connected to my code or the framework itself).

Does somebody experienced this behavior? What can be wrong?


Edit:

I edited both services. One got a nice try-catch everywhere and more logging. The second got a timer-recreation on a regular basis. None of them stopped since them, so if this situation remains for another week, I will close this question. Thank you for everyone so far.


Edit:

I close this question because nothing happened. I mean I made some changes, but those changes are not really relevant in this matter and both services are running without any problem since then. Please mark it as "Closed for not relevant anymore".

A: 

Is there anything in the event log after the timer stops running?

brien
Nothing at all. I can catch the tickTack_Elapsed function, but it is not called anymore. So the log shows that from starting the service I got events every 10 minutes but after a while it just stops without any error message or anything else. Can I log somehow more details?
Biri
A: 

Have you checked the error logs? Maybe you run out of timers somehow. Maybe you can create just one timer when you initialize the ArchiveService and skip the OnStart stuff.

PEZ
The timer is created only once. The OnStart is running only when I start the service itself, not every time it would like to do something.
Biri
+5  A: 

I have seen this before with both timer, and looped services. Usually the case is that an exception is caught that stops the timer or looping thread, but does not restart it as part of the exception recovery.

To your other points... I dont think that there is anything "elegant" about the timer. For me its more straight forward to see a looping operation in code than timer methods. But Elegance is subjective.

Memory issue? Not if you write it properly. Maybe a processor burden if your Thread.Sleep() isn't set right.

StingyJack
My last idea was that I will connect to the service with VS to debug it. Hopefully I could get the exception whereever it happens. I will also rewrite one of them to a loop. It worth a try.
Biri
You may want to have a loop that periodically checks the timer to see if its running, or to check the other loop. I use this to automatically restart a stopped timer or loop thread.
StingyJack
Also a good idea, thanks.
Biri
A: 

I have made exactly the same as you in a few projects but have not had the problem.

Do you have code in the tickTac_Elapsed that can be causing this? Like a loop that never ends or some error that stops the timer, using threads and waiting for ending of those and so on?

Stefan
Unfortunately no. The tickTack_Elapsed is working right, I log when it starts and ends. Every time I see a start-stop event pair before it stops responding. Furhermore I also check the running state in there, so it cannot run over to a previously started instance.
Biri
+2  A: 

Interesting issue. If it is truly just time related (i.e. not an exception), then I wonder if you can simply periodically recycle the timer - i.e.

private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
{
    CheckForRecycle();
    // ... actual code
}

private void CheckForRecycle()
{
    lock(someLock) {
        if(++tickCount > MAX_TICKS) {
            tickCount = 0;
            tickTack.Stop();
            // re-create timer
            tickTack = new Timer(...);
            tickTack.Elapsed += ...
            tickTack.Start();
        }
    }
}

You could probably merge chunks of this with the OnStart / OnStop etc to reduce duplication.

Marc Gravell
Interesting idea, I will give it a try this week for sure.
Biri
+11  A: 

unhandled exceptions in timers are swallowed, and they silently kill the timer

wrap the body of your timer code in a try-catch block

Steven A. Lowe
I will try this one also.
Biri
from my experience this problem is pretty much always due to an unhandled exception of the timer elasped delegate thread, ie "what Steven said!"
RhysC
That seems like terrible default behavior, but I've seen this before too.
rwmnau
+3  A: 

http://support.microsoft.com/kb/842793

This is a known bug that has resurfaced in the Framework more than once.

The best known work-around: don't use timers. I've rendered this bug ineffective by doing a silly "while (true)" loop.

Your mileage may vary, so verify with your combination of OS/Framework bits.

jro
Sorry, I forgot to mention that this is a .NET 2.0 application. But I also don't stop and restart the timer, however there are some points to consider (like using System.Threading instead of System.Timers). I add to my list to try, thanks.
Biri
I had the same effect as you -- I never stopped/restarted the timer, either. Nonetheless, through detailed logging I was able to ascertain that the timer simply stopped firing events.
jro
A: 

hi just enable the timer it wil get into elapsed time

A: 

Hi, How did you solve your problem ? I have exactly the same problem, but I don't know how to fix it. I'm running a service written in C# with a timer inside that is instantiated just once in OnStart(). My timer_Elapsed method is in a try...catch block and I Log the exception in a file which I tested if I throw an exception inside my code explicitly, it is logged as expected. The service runs properly about 1 day(maybe less or more) but it stops working without any log. at OnStop() method I even Log to the file, but there is no log text after this happens. this service is running on windows server 2003, can anyone help please?

here is the part of code that i log:

        try
        {
            ...
        }
        catch (Exception ex)
        {
            string CR = "\r\n";
            string log = "Exception Occured, " + DateTime.Now.ToString() + CR;
            log += ex.GetType().ToString() + ": " + ex.Message + CR + "InnerException: "
                + (ex.InnerException != null ? ex.InnerException.GetType().ToString() + CR + ex.InnerException.Message : "")
                + CR + "*****" + CR;
            System.IO.File.AppendAllText(@"D:\a.sadri\LOGs\LgnMgrLOG.txt", log);
            System.IO.File.AppendAllText(@"D:\a.sadri\LOGs\LgnMgrLOG.txt", "\r\n");
        }
        finally
        {
            daa.Dispose();
        }
Ashkan