예제 #1
0
 /// <summary>
 /// Raises the RetrieveVirtualItem event.
 /// </summary>
 /// <param name="e">A VirtualItemThumbnailEventArgs that contains event data.</param>
 protected virtual void OnRetrieveVirtualItemThumbnail(VirtualItemThumbnailEventArgs e)
 {
     if (RetrieveVirtualItemThumbnail != null)
         RetrieveVirtualItemThumbnail(this, e);
 }
        /// <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
                                    thumbCache.Remove(guid);
                            }
                        }
                        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, Color.White);

                        // 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, Color.White);
                            }
                        }

                        // 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)
                                {
                                    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;
            }
        }
예제 #3
0
 /// <summary>
 /// Raises the RetrieveVirtualItem event.
 /// This method is invoked from the thumbnail thread.
 /// </summary>
 /// <param name="e">A VirtualItemThumbnailEventArgs that contains event data.</param>
 internal virtual void RetrieveVirtualItemThumbnailInternal(VirtualItemThumbnailEventArgs e)
 {
     OnRetrieveVirtualItemThumbnail(e);
 }
예제 #4
0
        /// <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
                                {
                                    thumbCache.Remove(guid);
                                }
                            }
                        }
                        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, Color.White);
                        }

                        // 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, Color.White);
                            }
                        }

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