2013-11-29 1 views
1

У меня есть служба в моем ServiceStack API для обработки результатов изображения, реализуя IStreamWriter WriteTo (поток). Прекрасно работает.Как избавиться от результата InMemory Cached в ServiceStack

Чтобы оптимизировать обработку, я добавляю поддержку кэш-памяти InMemory, а TimeSpan истекает. Моя забота связана с IDispose. До реализации кэша я использовал IDispose для удаления объекта результата и его образа после его возвращения, но с кэшем inmemory он не может реализовать IDispose, в противном случае данные будут удалены до того, как они будут извлечены из кеша.

Вопрос в том, как или где реализовать реализацию кэшированных результатов? Будет ли кеш располагать элементы по истечении срока действия? Если да, то как реализовать Dispose только для вызовов из диспетчера кэша, но не из обработчика http.

public class ImageResult : IDisposable, IStreamWriter, IHasOptions 
{ 
    private readonly Image image; 

    public void WriteTo(Stream responseStream) 
    { 
     image.Save(responseStream, imgFormat); 
    } 

    public void Dispose() 
    { 
     // if we dispose here, will be disposed after the first result is returned 
     // want the image to be disposed on cache expiration 
     //if (this.image != null) 
     // this.image.Dispose(); 
    } 
} 

public class ImageService : AssetService 
{ 
    public object Get(ImageRequest request) 
    { 
     var cacheKey = ServiceStack.Common.UrnId.Create<ImageRequest>(request.id); 

     if (Cache.Get<ImageResult>(cacheKey) == null) 
     { 
      Cache.Set<ImageResult>(cacheKey, GetImage(request), TimeSpan.FromMinutes(1)); 
     } 

     return Cache.Get<ImageResult>(cacheKey); 
    } 
    [...] 
} 

ответ

1

С беглым взглядом на ServiceStack-х InMemoryCache вы можете увидеть, что нет ни одного события или обратного вызова вклиниться для истечения срока действия записи кэша. Подумайте, используя System.Runtime.Caching.MemoryCache, который дает вам аналогичные возможности кэширования, а также специально вы можете использовать монитор изменений для обратного вызова при истечении и/или удалении.

Другая альтернатива: создайте свой собственный исходный код кэша SS, чтобы предоставить вам обратный вызов.

После того как вы обратный вызов на месте, вы могли бы назвать Dispose() оттуда - но, как вы сказали, что вы не хотите, чтобы ImageResult быть одноразовым, а не разрешить доступ к своей собственности Image и распоряжаться, что от обратного вызова срока действий самостоятельно. Вы можете обернуть класс вокруг изображения .net, чтобы позволить модульное тестирование (не нужно использовать реальный объект изображения в тестах).

EDIT: на самом деле .. см. Ниже (*), это создаст беспорядок.

В другой заметке я внес бы некоторые изменения в метод Get(). Последний вызов Cache.Get() является излишним. Несмотря на то, что вы используете кеш в памяти, вы все равно хотите минимизировать доступ к нему, поскольку он потенциально медленнее, чем может показаться (необходимо использовать блокировки для синхронизации доступа в памяти из нескольких потоков).

var imageResult = Cache.Get<ImageResult>(cacheKey); 
    if (imageResult == null) 
    { 
     imageResult = GetImage(request); 
     Cache.Set<ImageResult>(cacheKey, imageResult, TimeSpan.FromMinutes(1)); 
    } 

    return imageResult; 

(*) Просто понял, что вы могли бы получить, что запрос ImageResult из кэша, а затем экземпляр позже, прежде чем он пишет что-либо в поток целевого (ответ), он истекает и получает утилизировать. Насти. Вместо этого пусть .net обрабатывает это для вас: вместо создания ImageResult реализует IDisposable, создайте деструктор, в котором вы разместите внутренний объект Image. Это будет работать с SS в кеше памяти:

~ImageResult() 
    { 
     image.Dispose(); 
    } 
+0

Я приведу этот снимок и обновит, забавно, как иногда мы забываем о добром деструкторе. (и да, действительно, на излишнем выигрыше - лучше доработать его, как было предложено.) – sirthomas

+0

классный. один (крайний) пример избыточного get вернет вам объект в первом вызове и вернет null во втором вызове, поскольку он истек между вызовами. – Jonno

Смежные вопросы