views:

250

answers:

2

I have a self-hosted WCF service and I'm having the following problem: 15 minutes after creating the instance of the service TryEnter calls in operation contract methods constantly return false, but the TryEnter calls in Main function, which also uses synchronization via Monitor class, return true.

Here's the description of my app and the bug: I am developing a self-hosted WCF service in Visual Studio 2008 (C#) in Windows XP SP2. The ServiceHost instance of the host is created at the beginning of the Main function. The Main function runs a while (true) loop during which it performs periodic readings, writing, maintenance etc. There is a static collection of objects (which can be added or removed over time), which act as containers for worker threads. Some of these threads do periodic work requested by Main function, while others perform on-demand reading and writing to a remote device. Synchronization locking is done on these objects using Monitor class (TryEnter and Exit methods). These objects are also accessed through the service contract methods (services) using the same functions. Synchronization is done between the Main function and the service methods. When the instance of the service is created, it runs with designed performance for exactly 15 minutes, after which every TryEnter(obj, timeout) call made from the service returns false after the specified timeout expires. This however doesn't affect the TryEnter calls made in the Main function i.e. they always return true. I have tried changing the settings for InstanceContextMode, ConcurrencyMode, coupled with service throttling attributes maxConcurrentCalls="1" ; maxConcurrentSessions="5" and every configuration gave the same effect. The service becomes responsive again when I restart the host app, but not when I forcibly close and reopen the host while the app is running (the service instance remains in the memory). It is not a case of service being unavailable, as in the call never making its way to the service instance. The method is called, its execution comes to the TryEnter call which precedes the critical section of the method and TryEnter just returns false after the timeout (15 seconds). I have checked and double checked the pairings of TryEnter and Exit – the methods always release the lock when the critical section ends. Other contract operations which don’t use locking or the objects in question work fine even after the 15 minute period has ended.

Thank you all in advance. Happy holidays!

+1  A: 

Monitor is re-entrant, so it sounds like the thread with your Main method has failed to release a lock. So when it asks for the lock (TryEnter) it gets the lock (incrementing the counter by another one).

All other threads will be denied. You will need to debug where the lock gets taken and held.

I have checked and double checked the pairings of TryEnter and Exit – the methods always release the lock when the critical section ends

sorry, but I think you're going to treble-check. In particular, unlike lock, TryEnter won't have any special exception handling. Your code should look like:

if(Monitor.TryEnter(lockObj, timeout)) {
    try {
        ...
    } finally {
        Monitor.Exit(lockObj);
    }
}

Also - ensure that you never reasign your lockObj in the code, as this won't unlock the correct object.

(or similar using a flag, especially in .NET 4.0 where there are new overloads for Enter etc)

Marc Gravell
A: 

Thanks, Marc, treble-check did the trick :).

As it happens, there was a periodic action which repeated itself every 5 minutes and it was that very one that was missing a Monitor.Exit(lockObj) call.

Also, I use a modified version of what you suggested the locking block should look like - I've added a catch block also, which handles other issues which don't concern synchronization.

I'll be sure to look at the new overloads, as soon as my boss OKs the use of the new version of .NET.

Thanks again and all the best!

antoine