Question

I have a WCF service hosted in a Windows Service (running under Local System). I am running a System.Timer inside it. The Operation o1, that initializes the Timer, is declared over a http endpoint over webHttpBinding. I enabled tracing for System.ServiceModel and from the .svcLog file I checked the Listen Duration for the Operation o1. It shows that, after running for approx 20 hours the Listening at the http endpoint just stops.

I think the this due to the fact that no incoming message arrived at that endpoint. The issue here is with the Listening coming to a stop, my timer(which was initialized inside that particular Operation o1) also stops!

Is there a recommended way to keep the Listener, and hence the timer, up for long durations? Can we periodically ping the o1 Operation to keep it in memory?

Also, my timer variable that I initialize inside the Operation o1 is an instance variable, isn't this variable expected to be in memory (the WCF being a Singleton) even if the Listener closes??

Thanks so much.

Code Exceprts-

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class SchedulerWindows : ISchedulerWindows
{
    ///.........all instance variables.....
    DataTimer timer = null; /**DataTimer wraps a System.Timers timer variable**/
    public List<DataTimer> timersInService = new List<DataTimer>();
    public ISchedulerWindows.o1(string s1, string s2, /*********/)
    {
     //..........//
     timer = new DataTimer();
    }
}

public class DataTimer
    {

        /****Newly introduced System.Threading.Timer, previously I was using        System.Timers.Timer which was dying****/

        public System.Threading.Timer thTimer;
        private static readonly object dbAccessLock = new object();
        private static readonly object thCallbackLock = new object();

        public DataTimer()
        {
        }

        public DataTimer(/************/)
        {            
            TimerCallback timerDelegate = new TimerCallback(this.WorkMethod);
            EventLogLogger l = new EventLogLogger();
            //l.LogMessage("setting up timer ");
            thTimer = new Timer(this.WorkMethod, null, 0, period);
        }
...
}

EDIT: Changing to System.Threading namespace from System.Timers namespace AND increasing the timed interval fixed it for me. The timer variable doesn't disappear anymore.

Was it helpful?

Solution

The most likely cause for your issue is InstanceContextMode. If you want your service instance to always be in memory you should use Single. You probably have PerSession or PerCall and that would explain why your timer is disappearing. You mention that your service is singleton but the symptoms are very suspicious. The service instance stays in memory until you shutdown host.

[ServiceBehavior(
         ConcurrencyMode = ConcurrencyMode.Multiple, 
         InstanceContextMode = InstanceContextMode.Single
)]

From WCF instance management:

The singleton service lives forever, and is only disposed of once the host shuts down. The singleton is created exactly once when the host is created.

EDIT: You probably checked that windows service is still running when your listener stops listening and timer disappears. It would also make sense to see if ServiceHost itself stays in memory. You can also put some logging in ServiceHosts 'Closing', 'Closed' and 'Faulted' event handlers.

EDIT 2: If your timer is disappearing than you should look at how you allocate it. It most likely gets garbage collected. You have to declare it as an instance field that is reachable from live objects. Make it static to be absolutely sure. You do it for DataTimer but it is not clear how the timer is declared and allocated inside DataTimer. Post some code please.

EDIT 3: You should not create timers in the operation. What happens if operation get called more than once? What happens to the old timer? I don't see how you close/dispose it. You also seem to have two constructors for DataTimer. One of them is doing nothing. And on top of that you have separate list of timers. This is a bit convoluted. Please isolate the problem and maybe post new code after that.

OTHER TIPS

I've not come across this issue specifically - however, if you just want the timer running while the service is running why not make it static. Then your instance context mode and instance lifetime won't affect your functionality.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top