ObjectCache CachedObjectRemovedCallback не вызывается?

У меня есть служба WCF, которая реализует пользовательский объектный кэш для кэширования стороннего COM-объекта для взаимодействия со средой 3270.

Этот сторонний объект работает по лицензионной модели, поэтому обязательно, чтобы мой RemovedCallBack вызывался каждый раз, когда объект удаляется из кэша, чтобы освободить лицензии.

Моя проблема в том, что я продолжаю получать лицензии, но в ObjectCache ничего не остается. Кажется, что элементы удаляются из кэша, но не обращаются к обратному вызову. Это возможно? Если мои кэшированные объекты будут очищены с помощью GC, они также будут выполнять обратный вызов?

Вот моя реализация:

private static readonly ObjectCache cache = MemoryCache.Default;

Элементы добавляются в кеш с помощью:

   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);
        }

и удаленный обратный вызов:

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();
            }
        }

1 ответ

Решение

Я думаю, что гораздо лучшим решением этой проблемы является полное исключение удаленного обратного вызова и обертывание вашего COM-объекта специальным классом с финализатором для вызова ReleaseSession(). Еще лучше было бы реализовать пул объектов для ваших объектов COM.

В вашей текущей реализации (с использованием удаленного обратного вызова) кто-то может вынуть объект из кэша, и, прежде чем он это сделает, кеш решает урезать, удаляя тот же объект из кэша.

Существуют некоторые опасности при выполнении COM-вызовов из потока финализатора (объекты STA могут блокировать финализатор, например, если поток STA не качает), но не хуже, чем ваша текущая реализация.

Другие вопросы по тегам