private void ThumbnailBuilt(object sender, ThumbnailBuiltEventArgs e)
        {
            ThumbnailData thumbnailData = null;

            if (e.ThumbnailStream != null)
            {
                var stream = new MemoryStream();
                e.ThumbnailStream.CopyTo(stream);
                thumbnailData = new BitmapThumbnailData(e.ThumbnailId, stream);
            }

            if (e.Result != ThumbnailBuildResult.Cancelled)
            {
                ThumbnailCompleted?.Invoke(this, new ThumbnailCompletedArgs(e.AssetId, thumbnailData));
            }

            lock (hashLock)
            {
                ThumbnailContinuation thumbnailContinuation;
                thumbnailsInProgressAndContinuation.TryGetValue(e.AssetId, out thumbnailContinuation);
                thumbnailsInProgressAndContinuation.Remove(e.AssetId);

                // Check if same asset has been requested again while it was compiling
                if (thumbnailContinuation != null)
                {
                    var priority = thumbnailContinuation.Position == QueuePosition.First ? firstPriority-- : lastPriority++;
                    var node     = assetBuilderService.PushBuildUnit(new ThumbnailAssetBuildUnit(thumbnailContinuation.UpdatedAssetToRecompile, currentGameSettings, this, priority));
                    thumbnailQueueHash.Add(thumbnailContinuation.UpdatedAssetToRecompile, node);
                }
            }
        }
        /// <summary>
        /// Notify that the thumbnail has just been built. This method will raise the <see cref="ThumbnailBuilt"/> event.
        /// </summary>
        /// <param name="assetItem">The asset item whose thumbnail has been built.</param>
        /// <param name="result">A <see cref="ThumbnailBuildResult"/> value indicating whether the build was successful, failed or cancelled.</param>
        /// <param name="changed">A boolean indicating whether the thumbnal has changed since the last generation.</param>
        /// <param name="thumbnailStream">A stream to the thumbnail image.</param>
        /// <param name="thumbnailHash"></param>
        internal void NotifyThumbnailBuilt(AssetItem assetItem, ThumbnailBuildResult result, bool changed, Stream thumbnailStream, ObjectId thumbnailHash)
        {
            try
            {
                // TODO: this lock seems to be useless now, check if we can safely remove it
                Monitor.Enter(thumbnailCounterLock);
                var handler = ThumbnailBuilt;
                if (handler != null)
                {
                    // create the thumbnail build event arguments
                    var thumbnailBuiltArgs = new ThumbnailBuiltEventArgs
                    {
                        AssetId          = assetItem.Id,
                        Url              = assetItem.Location,
                        Result           = result,
                        ThumbnailChanged = changed
                    };

                    Monitor.Exit(thumbnailCounterLock);

                    // Open the image data stream if the build succeeded
                    if (thumbnailBuiltArgs.Result == ThumbnailBuildResult.Succeeded)
                    {
                        thumbnailBuiltArgs.ThumbnailStream = thumbnailStream;
                        thumbnailBuiltArgs.ThumbnailId     = thumbnailHash;
                    }
                    else if (BuildFailedThumbnail != null)
                    {
                        thumbnailBuiltArgs.ThumbnailStream = new MemoryStream(BuildFailedThumbnail.Result);
                    }
                    handler(assetItem, thumbnailBuiltArgs);
                }
            }
            finally
            {
                if (Monitor.IsEntered(thumbnailCounterLock))
                {
                    Monitor.Exit(thumbnailCounterLock);
                }
            }
        }