Domanda

I have a WCF service that is implementing a custom ObjectCache to cache a 3rd party COM object for interfacing with a 3270 environment.

This 3rd party object works on a licensed model, so it's imperative that my RemovedCallBack be called each time an object is removed from the cache in order to free up licenses.

My problem is, I keep getting used licenses, but nothing remains in the ObjectCache. This seems like items are getting removed from the cache, but not hitting the callback. Is this possible? If my cached objects are getting cleaned up by the GC, would they also hit the callback?

Here's my implementation:

private static readonly ObjectCache cache = MemoryCache.Default;

Items are being added to the cache using:

   public void AddToCache(String cacheKeyName, object cacheObject, int expiryMinutes)
        {
            callback = CachedObjectRemovedCallback;

            // Sliding expiration
            policy = new CacheItemPolicy
            {
                Priority = CacheItemPriority.Default,
                SlidingExpiration = TimeSpan.FromMinutes(expiryMinutes),
                RemovedCallback = callback
            };

            // Add to cache
            cache.AddOrGetExisting(cacheKeyName, cacheObject, policy);
        }

and the removed callback:

private CacheEntryRemovedCallback callback;
private static void CachedObjectRemovedCallback(CacheEntryRemovedArguments arguments)
        {
            // Always check if the object is a customtype, and if so, release the session/license
            if (arguments.CacheItem != null && IsCustomType(arguments.CacheItem.Value))
            {
                // Release the custom session
                ICustomType customType= (ICustomType)arguments.CacheItem.Value;
                customType.ReleaseSession();
            }
        }
È stato utile?

Soluzione

I think a much better solution to this problem is avoiding the removed callback entirely, and wrapping your COM object with a custom class that has a finalizer to do the ReleaseSession() call. Even better though would be to implement some kind of object pooling for your COM objects.

In your current implementation (using the removed callbacked), it's possible for someone to take the object out of the cache, and before they're done with it, the cache decides to trim, removing the same object from the cache.

There are some dangers with doing COM calls from the finalizer thread (STA objects may block the finalizer if the STA thread isn't pumping for example), but no worse than your current implementation.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top