/// <summary>
        /// Removes the given item from the cache.
        /// </summary>
        /// <param name="guid">The guid of the item to remove.</param>
        /// <param name="removeNow">true to remove the item now; false to remove the
        /// item later when the cache is purged.</param>
        public void Remove(Guid guid, bool removeNow)
        {
            CacheItem cacheItem = null;

            if (!thumbCache.TryGetValue(guid, out cacheItem))
            {
                return;
            }

            if (removeNow)
            {
                MemoryUsed -= GetImageMemorySize(cacheItem.Size.Width, cacheItem.Size.Height);
                cacheItem.Dispose();
                thumbCache.Remove(guid);
            }
            else
            {
                MemoryUsedByRemoved += GetImageMemorySize(cacheItem.Size.Width, cacheItem.Size.Height);
                removedItems.Add(guid);

                Purge();
            }

            // Remove from disk cache
            ImageListViewItem item = null;

            if (mImageListView != null && mImageListView.Items.TryGetValue(guid, out item))
            {
                string diskCacheKey = item.Adaptor.GetUniqueIdentifier(item.VirtualItemKey, cacheItem.Size, cacheItem.UseEmbeddedThumbnails, cacheItem.AutoRotate, cacheItem.UseWIC);
                diskCache.Remove(diskCacheKey);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Handles the RunWorkerCompleted event of the queued background worker.
        /// [IG_CHANGE] Issue #359: thread collision? leftover context? failed to check null
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="ImageGlass.ImageListView.QueuedWorkerCompletedEventArgs"/>
        /// instance containing the event data.</param>
        void bw_RunWorkerCompleted(object sender, QueuedWorkerCompletedEventArgs e)
        {
            CacheItem result = e.Result as CacheItem;

            // Add to cache
            if (result != null)
            {
                // We are done processing
                bool removedValue;
                var  removed = processing.TryRemove(result.Extension, out removedValue);
                if (!removed)
                {
                    throw new InvalidOperationException("processing.TryRemove failed");
                }

                CacheItem existing = null;
                if (shellCache.TryGetValue(result.Extension, out existing))
                {
                    existing.Dispose();
                    shellCache.Remove(result.Extension);
                }
                shellCache.Add(result.Extension, result);
            }

            // Refresh the control lazily
            if (result != null && mImageListView != null)
            {
                mImageListView.Refresh(false, true);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Handles the RunWorkerCompleted event of the queued background worker.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Manina.Windows.Forms.QueuedWorkerCompletedEventArgs"/>
        /// instance containing the event data.</param>
        void bw_RunWorkerCompleted(object sender, QueuedWorkerCompletedEventArgs e)
        {
            CacheItem result = e.Result as CacheItem;

            // We are done processing
            processing.Remove(result.Extension);

            // Add to cache
            if (result != null)
            {
                CacheItem existing = null;
                if (shellCache.TryGetValue(result.Extension, out existing))
                {
                    existing.Dispose();
                    shellCache.Remove(result.Extension);
                }
                shellCache.Add(result.Extension, result);
            }

            // Refresh the control lazily
            if (result != null && mImageListView != null)
            {
                mImageListView.Refresh(false, true);
            }
        }
Esempio n. 4
0
        private static void OnProxyDisposed(CacheItemProxy cacheItemProxy)
        {
            ReferenceCountedObjectWrapper <CacheItem> wrapper = cacheItemProxy.Wrapper;

            if (!wrapper.IsReferenceCountAboveZero())
            {
                lock (_syncLock)
                {
                    //The count could have gone back up
                    if (wrapper.IsReferenceCountAboveZero())
                    {
                        return;
                    }

                    CacheItem cacheItem = wrapper.Item;
                    _cache.Remove(cacheItem.Key);
                    cacheItem.Dispose();

                    if (_cache.Count == 0)
                    {
                        Trace.WriteLine("The composed lut cache is empty.", "LUT");
                    }
                }
            }
        }
 /// <summary>
 /// Adds a virtual item to the cache queue.
 /// </summary>
 /// <param name="guid">The guid representing this item.</param>
 /// <param name="key">The key of this item.</param>
 /// <param name="thumbSize">Requested thumbnail size.</param>
 /// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
 public void Add(Guid guid, object key, Size thumbSize,
                 UseEmbeddedThumbnails useEmbeddedThumbnails)
 {
     lock (lockObject)
     {
         // Already cached?
         CacheItem item = null;
         if (thumbCache.TryGetValue(guid, out item))
         {
             if (item.Size == thumbSize && item.UseEmbeddedThumbnails == useEmbeddedThumbnails)
             {
                 return;
             }
             else
             {
                 item.Dispose();
                 thumbCache.Remove(guid);
             }
         }
         // Add to cache
         toCache.Push(new CacheItem(guid, key, thumbSize, null,
                                    CacheState.Unknown, useEmbeddedThumbnails));
         Monitor.Pulse(lockObject);
     }
 }
Esempio n. 6
0
        private void RemoveAt(int index)
        {
            CacheItem item = FPages[index];

            FPages.RemoveAt(index);
            item.Dispose();
        }
        /// <summary>
        /// Purges removed items from the cache.
        /// </summary>
        /// <param name="force">true to purge the cache now, regardless of
        /// memory usage; otherwise false to automatically purge the cache
        /// depending on memory usage.</param>
        public void Purge(bool force)
        {
            // Remove items now if we can free more than 25% of the cache limit
            if (force || IsPurgeNeeded())
            {
                foreach (Guid guid in removedItems)
                {
                    CacheItem item = null;
                    if (thumbCache.TryGetValue(guid, out item))
                    {
                        item.Dispose();
                        thumbCache.Remove(guid);
                    }

                    if (galleryItem != null && galleryItem.Guid == guid)
                    {
                        galleryItem.Dispose();
                        galleryItem = null;
                    }
                }
                removedItems.Clear();
                MemoryUsed         -= MemoryUsedByRemoved;
                MemoryUsedByRemoved = 0;
            }
        }
Esempio n. 8
0
        private void RemoveAt(int index)
        {
            CacheItem item = pages[index];

            item.Dispose();
            item = null;
            pages.RemoveAt(index);
        }
 /// <summary>
 /// Ends editing an item. After this call, item
 /// image will be continued to be fetched from the
 /// file.
 /// </summary>
 /// <param name="guid">The guid representing the item.</param>
 public void EndItemEdit(Guid guid)
 {
     lock (lockObject)
     {
         if (editCache.ContainsKey(guid))
         {
             editCache[guid].Dispose();
             editCache.Remove(guid);
         }
         if (rendererGuid == guid)
         {
             rendererGuid = Guid.Empty;
             if (rendererItem != null)
             {
                 rendererItem.Dispose();
             }
         }
     }
 }
        /// <summary>
        /// Adds a virtual item to the cache.
        /// </summary>
        /// <param name="guid">The guid representing this item.</param>
        /// <param name="key">The key of this item.</param>
        /// <param name="thumbSize">Requested thumbnail size.</param>
        /// <param name="thumb">Thumbnail image to add to cache.</param>
        /// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
        public void Add(Guid guid, object key, Size thumbSize, Image thumb,
                        UseEmbeddedThumbnails useEmbeddedThumbnails)
        {
            lock (lockObject)
            {
                // Already cached?
                CacheItem item = null;
                if (thumbCache.TryGetValue(guid, out item))
                {
                    if (item.Size == thumbSize && item.UseEmbeddedThumbnails == useEmbeddedThumbnails)
                    {
                        return;
                    }
                    else
                    {
                        item.Dispose();
                        thumbCache.Remove(guid);
                    }
                }
                // Add to cache
                thumbCache.Add(guid, new CacheItem(guid, key, thumbSize, thumb,
                                                   CacheState.Cached, useEmbeddedThumbnails));
            }

            try
            {
                if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed)
                {
                    mImageListView.Invoke(new ThumbnailCachedEventHandlerInternal(
                                              mImageListView.OnThumbnailCachedInternal), guid, false);
                    mImageListView.Invoke(new RefreshDelegateInternal(
                                              mImageListView.OnRefreshInternal));
                }
            }
            catch (ObjectDisposedException)
            {
                if (!Stopping)
                {
                    throw;
                }
            }
            catch (InvalidOperationException)
            {
                if (!Stopping)
                {
                    throw;
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Removes the given item from the cache.
        /// </summary>
        /// <param name="extension">File extension.</param>
        public void Remove(string extension)
        {
            if (string.IsNullOrEmpty(extension))
            {
                throw new ArgumentException("extension cannot be null", "extension");
            }

            CacheItem item = null;

            if (shellCache.TryGetValue(extension, out item))
            {
                item.Dispose();
                shellCache.Remove(extension);
            }
        }
Esempio n. 12
0
        private void Delete(CacheItem item)
        {
            if (item.Value != null)
            {
                string[] itemKeys = item.Keys;
                item.Dispose();
                _expirations.RemoveExpiration(item);

                // Remove the lookup by this key to this item.
                foreach (string itemKey in itemKeys)
                {
                    _cache.Remove(itemKey);
                }
            }
        }
        /// <summary>
        /// Removes the given item from the cache.
        /// </summary>
        /// <param name="guid">The guid of the item to remove.</param>
        /// <param name="removeNow">true to remove the item now; false to remove the
        /// item later when the cache is purged.</param>
        public void Remove(Guid guid, bool removeNow)
        {
            lock (lockObject)
            {
                CacheItem item = null;
                if (!thumbCache.TryGetValue(guid, out item))
                {
                    return;
                }

                if (removeNow)
                {
                    memoryUsed -= item.Size.Width * item.Size.Height * 24 / 8;
                    item.Dispose();
                    thumbCache.Remove(guid);
                }
                else
                {
                    // Calculate the memory usage (approx. Width * Height * BitsPerPixel / 8)
                    memoryUsedByRemoved += item.Size.Width * item.Size.Height * 24 / 8;
                    removedItems.Add(guid);

                    // Remove items now if we can free more than 25% of the cache limit
                    if ((mCacheLimitAsMemory != 0 && memoryUsedByRemoved > mCacheLimitAsMemory / 4) ||
                        (mCacheLimitAsItemCount != 0 && removedItems.Count > mCacheLimitAsItemCount / 4))
                    {
                        CacheItem itemToRemove = null;
                        foreach (Guid iguid in removedItems)
                        {
                            if (thumbCache.TryGetValue(iguid, out itemToRemove))
                            {
                                itemToRemove.Dispose();
                                thumbCache.Remove(iguid);
                            }
                        }
                        removedItems.Clear();
                        memoryUsed         -= memoryUsedByRemoved;
                        memoryUsedByRemoved = 0;
                    }
                }
            }
        }
        /// <summary>
        /// Removes the given item from the cache.
        /// </summary>
        /// <param name="guid">The guid of the item to remove.</param>
        /// <param name="removeNow">true to remove the item now; false to remove the
        /// item later when the cache is purged.</param>
        public void Remove(Guid guid, bool removeNow)
        {
            CacheItem item = null;

            if (!thumbCache.TryGetValue(guid, out item))
            {
                return;
            }

            if (removeNow)
            {
                MemoryUsed -= GetImageMemorySize(item.Size.Width, item.Size.Height);
                item.Dispose();
                thumbCache.Remove(guid);
            }
            else
            {
                MemoryUsedByRemoved += GetImageMemorySize(item.Size.Width, item.Size.Height);
                removedItems.Add(guid);

                Purge();
            }
        }
        /// <summary>
        /// Used by the worker thread to generate image thumbnails.
        /// Once a thumbnail image is generated, the item will be redrawn
        /// to replace the placeholder image.
        /// </summary>
        private void DoWork()
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

            while (!Stopping)
            {
                Guid      guid            = new Guid();
                CacheItem request         = null;
                bool      rendererRequest = false;
                lock (lockObject)
                {
                    // Wait until we have items waiting to be cached
                    if (toCache.Count == 0 && rendererToCache.Count == 0)
                    {
                        Monitor.Wait(lockObject);
                    }
                }

                // Set to true when we exceed the cache memory limit
                bool cleanupRequired = false;
                // Set to true when we fetch at least one thumbnail
                bool thumbnailCreated = false;

                // Loop until we exhaust the queue
                bool queueFull = true;
                while (queueFull && !Stopping)
                {
                    lock (lockObject)
                    {
                        sw.Start();
                        // Get an item from the queue
                        if (toCache.Count != 0)
                        {
                            request = toCache.Pop();
                            guid    = request.Guid;

                            // Is it already cached?
                            CacheItem existing = null;
                            if (thumbCache.TryGetValue(guid, out existing))
                            {
                                if (existing.Size == request.Size)
                                {
                                    request = null;
                                }
                            }
                        }
                        else if (rendererToCache.Count != 0)
                        {
                            request = rendererToCache.Pop();
                            guid    = request.Guid;
                            rendererToCache.Clear();
                            rendererRequest = true;
                        }
                    }

                    // Is it outside visible area?
                    bool isvisible = true;
                    if (request != null && mCacheMode == CacheMode.OnDemand)
                    {
                        try
                        {
                            if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed)
                            {
                                isvisible = (bool)mImageListView.Invoke(new CheckItemVisibleDelegateInternal(
                                                                            mImageListView.IsItemVisible), guid);
                            }
                        }
                        catch (ObjectDisposedException)
                        {
                            if (!Stopping)
                            {
                                throw;
                            }
                        }
                        catch (InvalidOperationException)
                        {
                            if (!Stopping)
                            {
                                throw;
                            }
                        }
                    }

                    lock (lockObject)
                    {
                        if (!rendererRequest && !isvisible)
                        {
                            request = null;
                        }
                    }

                    // Proceed if we have a valid request
                    CacheItem result = null;
                    if (request != null)
                    {
                        Image thumb = null;

                        // Is it in the edit cache?
                        Image editSource = null;
                        lock (lockObject)
                        {
                            if (!editCache.TryGetValue(guid, out editSource))
                            {
                                editSource = null;
                            }
                        }
                        if (editSource != null)
                        {
                            thumb = Utility.ThumbnailFromImage(editSource, request.Size);
                        }

                        // Read thumbnail image
                        if (thumb == null)
                        {
                            if (request.IsVirtualItem)
                            {
                                VirtualItemThumbnailEventArgs e = new VirtualItemThumbnailEventArgs(
                                    request.VirtualItemKey, request.Size);
                                if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed)
                                {
                                    mImageListView.RetrieveVirtualItemThumbnailInternal(e);
                                }
                                if (e.ThumbnailImage != null)
                                {
                                    thumb = e.ThumbnailImage;
                                }
                            }
                            else
                            {
                                thumb = Utility.ThumbnailFromFile(request.FileName,
                                                                  request.Size, request.UseEmbeddedThumbnails);
                            }
                        }

                        // Create the cache item
                        if (thumb == null)
                        {
                            if (!mRetryOnError)
                            {
                                result = new CacheItem(guid, request.FileName,
                                                       request.Size, null, CacheState.Error, request.UseEmbeddedThumbnails);
                            }
                            else
                            {
                                result = null;
                            }
                        }
                        else
                        {
                            result = new CacheItem(guid, request.FileName,
                                                   request.Size, thumb, CacheState.Cached, request.UseEmbeddedThumbnails);
                            thumbnailCreated = true;
                        }

                        if (result != null)
                        {
                            if (rendererRequest)
                            {
                                lock (lockObject)
                                {
                                    if (rendererItem != null)
                                    {
                                        rendererItem.Dispose();
                                    }

                                    rendererGuid    = guid;
                                    rendererItem    = result;
                                    rendererRequest = false;
                                }
                            }
                            else
                            {
                                lock (lockObject)
                                {
                                    CacheItem existing = null;
                                    if (thumbCache.TryGetValue(guid, out existing))
                                    {
                                        existing.Dispose();
                                        thumbCache.Remove(guid);
                                    }
                                    thumbCache.Add(guid, result);

                                    if (thumb != null)
                                    {
                                        // Did we exceed the cache limit?
                                        memoryUsed += thumb.Width * thumb.Height * 24 / 8;
                                        if ((mCacheLimitAsMemory != 0 && memoryUsed > mCacheLimitAsMemory) ||
                                            (mCacheLimitAsItemCount != 0 && thumbCache.Count > mCacheLimitAsItemCount))
                                        {
                                            cleanupRequired = true;
                                        }
                                    }
                                }
                            }
                        }

                        try
                        {
                            if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed)
                            {
                                mImageListView.Invoke(new ThumbnailCachedEventHandlerInternal(
                                                          mImageListView.OnThumbnailCachedInternal), guid, (result == null));
                            }
                        }
                        catch (ObjectDisposedException)
                        {
                            if (!Stopping)
                            {
                                throw;
                            }
                        }
                        catch (InvalidOperationException)
                        {
                            if (!Stopping)
                            {
                                throw;
                            }
                        }
                    }

                    // Check if the cache is exhausted
                    lock (lockObject)
                    {
                        if (toCache.Count == 0 && rendererToCache.Count == 0)
                        {
                            queueFull = false;
                        }
                    }

                    // Do we need a refresh?
                    sw.Stop();
                    if (sw.ElapsedMilliseconds > 100)
                    {
                        try
                        {
                            if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed)
                            {
                                mImageListView.Invoke(new RefreshDelegateInternal(
                                                          mImageListView.OnRefreshInternal));
                            }
                            sw.Reset();
                        }
                        catch (ObjectDisposedException)
                        {
                            if (!Stopping)
                            {
                                throw;
                            }
                        }
                        catch (InvalidOperationException)
                        {
                            if (!Stopping)
                            {
                                throw;
                            }
                        }
                    }
                    if (queueFull)
                    {
                        sw.Start();
                    }
                    else
                    {
                        sw.Reset();
                        sw.Stop();
                    }
                }

                // Clean up invisible items
                if (cleanupRequired)
                {
                    Dictionary <Guid, bool> visible = new Dictionary <Guid, bool>();
                    try
                    {
                        if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed)
                        {
                            visible = (Dictionary <Guid, bool>)mImageListView.Invoke(
                                new GetVisibleItemsDelegateInternal(mImageListView.GetVisibleItems));
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        if (!Stopping)
                        {
                            throw;
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        if (!Stopping)
                        {
                            throw;
                        }
                    }

                    if (visible.Count != 0)
                    {
                        lock (lockObject)
                        {
                            foreach (KeyValuePair <Guid, CacheItem> item in thumbCache)
                            {
                                if (!visible.ContainsKey(item.Key) && item.Value.State == CacheState.Cached && item.Value.Image != null)
                                {
                                    removedItems.Add(item.Key);
                                    memoryUsedByRemoved += item.Value.Image.Width * item.Value.Image.Width * 24 / 8;
                                }
                            }
                            foreach (Guid iguid in removedItems)
                            {
                                if (thumbCache.ContainsKey(iguid))
                                {
                                    thumbCache[iguid].Dispose();
                                    thumbCache.Remove(iguid);
                                }
                            }
                            removedItems.Clear();
                            memoryUsed         -= memoryUsedByRemoved;
                            memoryUsedByRemoved = 0;
                        }
                    }
                }

                if (thumbnailCreated)
                {
                    try
                    {
                        if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed)
                        {
                            mImageListView.Invoke(new RefreshDelegateInternal(mImageListView.OnRefreshInternal));
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        if (!Stopping)
                        {
                            throw;
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        if (!Stopping)
                        {
                            throw;
                        }
                    }
                }
            }

            lock (lockObject)
            {
                stopped = true;
            }
        }
        /// <summary>
        /// Handles the RunWorkerCompleted event of the queued background worker.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="ImageGlass.ImageListView.QueuedWorkerCompletedEventArgs"/>
        /// instance containing the event data.</param>
        void bw_RunWorkerCompleted(object sender, QueuedWorkerCompletedEventArgs e)
        {
            CacheRequest request = e.UserState as CacheRequest;
            CacheItem    result  = e.Result as CacheItem;

            // We are done processing
            if (request.RequestType == RequestType.Renderer)
            {
                processingRendererItem = Guid.Empty;
            }
            else if (request.RequestType == RequestType.Gallery)
            {
                processingGalleryItem = Guid.Empty;
            }
            else
            {
                processing.Remove(request.Guid);
            }

            // Do not process the result if the cache operation
            // was cancelled.
            if (e.Cancelled)
            {
                return;
            }

            // Dispose old item and add to cache
            if (request.RequestType == RequestType.Renderer)
            {
                if (rendererItem != null)
                {
                    rendererItem.Dispose();
                }

                rendererItem = result;
            }
            else if (request.RequestType == RequestType.Gallery)
            {
                if (galleryItem != null)
                {
                    galleryItem.Dispose();
                }

                galleryItem = result;
            }
            else if (result != null)
            {
                CacheItem existing = null;
                if (thumbCache.TryGetValue(result.Guid, out existing))
                {
                    existing.Dispose();
                    thumbCache.Remove(result.Guid);
                }
                thumbCache.Add(result.Guid, result);

                if (result.Image != null)
                {
                    // Did the thumbnail size change while we were
                    // creating the thumbnail?
                    if (result.Size != mImageListView.ThumbnailSize)
                    {
                        result.State = CacheState.Unknown;
                    }

                    // Purge invisible items if we exceeded the cache limit
                    MemoryUsed += GetImageMemorySize(result.Image);
                    if (IsCacheLimitExceeded())
                    {
                        PurgeInvisible(true);
                    }
                }
            }

            //Refresh the control
            if (mImageListView != null)
            {
                if (request.RequestType != RequestType.Thumbnail || mImageListView.IsItemVisible(request.Guid))
                {
                    mImageListView.Refresh(false, true);
                }
            }

            // Raise the ThumbnailCached event
            if (mImageListView != null)
            {
                mImageListView.OnThumbnailCachedInternal(result.Guid, result.Image, result.Size, request.RequestType == RequestType.Thumbnail);
            }

            // Raise the CacheError event
            if (e.Error != null && mImageListView != null)
            {
                mImageListView.OnCacheErrorInternal(result.Guid, e.Error, CacheThread.Thumbnail);
            }
        }