private void GetTiles(IEnumerable <Tile> tiles, Dispatcher dispatcher, TileSource tileSource, string sourceName, int maxDownloads)
        {
            var useCache = Cache != null &&
                           !string.IsNullOrEmpty(sourceName) &&
                           !(tileSource is ImageTileSource) &&
                           !tileSource.UriFormat.StartsWith("file:");

            foreach (var tile in tiles)
            {
                ImageSource cachedImage = null;

                if (useCache && GetCachedImage(CacheKey(sourceName, tile), out cachedImage))
                {
                    dispatcher.BeginInvoke(new Action <Tile, ImageSource>((t, i) => t.SetImage(i)), tile, cachedImage);
                }
                else
                {
                    pendingTiles.Enqueue(new PendingTile(tile, cachedImage));
                }
            }

            var newTaskCount = Math.Min(pendingTiles.Count, maxDownloads) - taskCount;

            while (newTaskCount-- > 0)
            {
                Interlocked.Increment(ref taskCount);

                Task.Run(() => LoadPendingTiles(dispatcher, tileSource, sourceName));
            }
        }
Example #2
0
        /// <summary>
        /// Loads all pending tiles from the tiles collection.
        /// If tileSource.UriFormat starts with "http" and sourceName is a non-empty string,
        /// tile images will be cached in the TileImageLoader's Cache (if that is not null).
        /// </summary>
        public void LoadTiles(IEnumerable <Tile> tiles, TileSource tileSource, string sourceName)
        {
            tileQueue.Clear();

            tiles = tiles.Where(tile => tile.Pending);

            if (tiles.Any() && tileSource != null)
            {
                if (Cache != null &&
                    tileSource.UriFormat != null &&
                    tileSource.UriFormat.StartsWith("http") &&
                    !string.IsNullOrEmpty(sourceName))
                {
                    loadTile = tile => LoadCachedTileAsync(tile, tileSource, sourceName);
                }
                else
                {
                    loadTile = tile => LoadTileAsync(tile, tileSource);
                }

                tileQueue.Enqueue(tiles);

                while (taskCount < Math.Min(tileQueue.Count, MaxLoadTasks))
                {
                    Interlocked.Increment(ref taskCount);

                    Task.Run(() => LoadTilesFromQueueAsync());
                }
            }
        }
Example #3
0
        /// <summary>
        /// Loads all pending tiles from the tiles collection in up to MaxLoadTasks parallel Tasks.
        /// If the UriFormat of the TileSource starts with "http" and the sourceName string is non-empty,
        /// tile images are cached in the TileImageLoader's Cache.
        /// </summary>
        public void LoadTilesAsync(IEnumerable <Tile> tiles, TileSource tileSource, string sourceName)
        {
            tileQueue.Clear();

            if (tileSource != null)
            {
                tileQueue.Enqueue(tiles);

                var newTasks = Math.Min(tileQueue.Count, MaxLoadTasks) - taskCount;

                if (newTasks > 0)
                {
                    Func <Tile, Task> loadTileFunc;

                    if (Cache != null &&
                        tileSource.UriFormat != null &&
                        tileSource.UriFormat.StartsWith("http") &&
                        !string.IsNullOrEmpty(sourceName))
                    {
                        loadTileFunc = tile => LoadCachedTileImageAsync(tile, tileSource, sourceName);
                    }
                    else
                    {
                        loadTileFunc = tile => LoadTileImageAsync(tile, tileSource);
                    }

                    Interlocked.Add(ref taskCount, newTasks);

                    while (--newTasks >= 0)
                    {
                        Task.Run(() => LoadTilesFromQueueAsync(loadTileFunc));
                    }
                }
            }
        }
Example #4
0
        private async Task LoadPendingTilesAsync(TileSource tileSource, string sourceName)
        {
            Tile tile;

            while (pendingTiles.TryPop(out tile))
            {
                tile.Pending = false;

                try
                {
                    var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);

                    if (uri != null)
                    {
                        var extension = Path.GetExtension(uri.LocalPath);

                        if (string.IsNullOrEmpty(extension) || extension == ".jpeg")
                        {
                            extension = ".jpg";
                        }

                        var cacheKey = string.Format(CacheKeyFormat, sourceName, tile.ZoomLevel, tile.XIndex, tile.Y, extension);

                        await LoadTileImageAsync(tile, uri, cacheKey);
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("TileImageLoader: {0}/{1}/{2}: {3}", tile.ZoomLevel, tile.XIndex, tile.Y, ex.Message);
                }
            }
        }
        private async Task LoadTileImageAsync(Tile tile, TileSource tileSource, string sourceName)
        {
            if (tileSource != null)
            {
                if (Cache != null &&
                    tileSource.UriFormat != null &&
                    tileSource.UriFormat.StartsWith("http") &&
                    !string.IsNullOrEmpty(sourceName))
                {
                    var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);

                    if (uri != null)
                    {
                        var extension = Path.GetExtension(uri.LocalPath);

                        if (string.IsNullOrEmpty(extension) || extension == ".jpeg")
                        {
                            extension = ".jpg";
                        }

                        var cacheKey = string.Format(CacheKeyFormat, sourceName, tile.ZoomLevel, tile.XIndex, tile.Y, extension);

                        await LoadCachedTileImageAsync(tile, uri, cacheKey).ConfigureAwait(false);
                    }
                }
                else
                {
                    await LoadTileImageAsync(tile, tileSource).ConfigureAwait(false);
                }
            }
        }
Example #6
0
        /// <summary>
        /// Loads all pending tiles from the tiles collection.
        /// If tileSource.UriFormat starts with "http" and sourceName is a non-empty string,
        /// tile images will be cached in the TileImageLoader's Cache (if it's not null).
        /// The method is async void because it implements void ITileImageLoader.LoadTiles
        /// and is not awaited when it is called in MapTileLayer.UpdateTiles().
        /// </summary>
        public async void LoadTiles(IEnumerable <Tile> tiles, TileSource tileSource, string sourceName)
        {
            tileQueue.Clear();

            tiles = tiles.Where(tile => tile.Pending);

            if (tiles.Any() && tileSource != null)
            {
                if (Cache != null &&
                    tileSource.UriFormat != null &&
                    tileSource.UriFormat.StartsWith("http") &&
                    !string.IsNullOrEmpty(sourceName))
                {
                    loadTileImage = tile => LoadCachedTileImageAsync(tile, tileSource, sourceName);
                }
                else
                {
                    loadTileImage = tile => LoadTileImageAsync(tile, tileSource);
                }

                tileQueue.Enqueue(tiles);

                var numTasks = Math.Min(tileQueue.Count, MaxLoadTasks);
                var tasks    = Enumerable.Range(0, numTasks).Select(n => LoadTilesFromQueueAsync());

                await Task.WhenAll(tasks).ConfigureAwait(false);
            }
        }
        private static async Task LoadTileImageAsync(Tile tile, TileSource tileSource)
        {
            var image = await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel).ConfigureAwait(false);

            if (image != null)
            {
                SetTileImageAsync(tile, image);
            }
        }
        private async Task LoadPendingTiles(TileSource tileSource, string sourceName)
        {
            PendingTile pendingTile;
            var         cache = Cache;

            if (cache == null || sourceName == null)
            {
                while (pendingTiles.TryDequeue(out pendingTile))
                {
                    await DownloadImage(pendingTile.Tile, pendingTile.Image, pendingTile.Uri, null);
                }
            }
            else
            {
                while (pendingTiles.TryDequeue(out pendingTile))
                {
                    var tile      = pendingTile.Tile;
                    var image     = pendingTile.Image;
                    var uri       = pendingTile.Uri;
                    var extension = Path.GetExtension(uri.LocalPath);

                    if (string.IsNullOrEmpty(extension) || extension == ".jpeg")
                    {
                        extension = ".jpg";
                    }

                    var cacheKey  = string.Format(@"{0}\{1}\{2}\{3}{4}", sourceName, tile.ZoomLevel, tile.XIndex, tile.Y, extension);
                    var cacheItem = await cache.GetAsync(cacheKey);

                    var loaded = false;

                    if (cacheItem == null || cacheItem.Expiration <= DateTime.UtcNow)
                    {
                        loaded = await DownloadImage(tile, image, uri, cacheKey);
                    }

                    if (!loaded && cacheItem != null && cacheItem.Buffer != null)
                    {
                        using (var stream = new InMemoryRandomAccessStream())
                        {
                            await stream.WriteAsync(cacheItem.Buffer);

                            await stream.FlushAsync();

                            stream.Seek(0);

                            await LoadImageFromStream(tile, image, stream);
                        }
                    }
                }
            }

            Interlocked.Decrement(ref taskCount);
        }
Example #9
0
        private static ImageSource CreateImage(TileSource tileSource, Tile tile)
        {
            ImageSource image = null;

            try
            {
                image = BitmapFrame.Create(tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel));
            }
            catch (Exception ex)
            {
                Trace.TraceWarning("Creating tile image failed: {0}", ex.Message);
            }

            return(image);
        }
Example #10
0
        private void LoadPendingTiles(Dispatcher dispatcher, TileSource tileSource, string sourceName)
        {
            var         imageTileSource = tileSource as ImageTileSource;
            PendingTile pendingTile;

            while (pendingTiles.TryDequeue(out pendingTile))
            {
                var         tile  = pendingTile.Tile;
                ImageSource image = null;

                if (imageTileSource != null)
                {
                    image = LoadImage(imageTileSource, tile);
                }
                else
                {
                    var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);

                    if (uri != null)
                    {
                        if (!uri.IsAbsoluteUri)
                        {
                            image = LoadImage(uri.OriginalString);
                        }
                        else if (uri.Scheme == "file")
                        {
                            image = LoadImage(uri.LocalPath);
                        }
                        else
                        {
                            image = DownloadImage(uri, CacheKey(sourceName, tile))
                                    ?? pendingTile.CachedImage; // use possibly cached image if download failed
                        }
                    }
                }

                if (image != null)
                {
                    dispatcher.BeginInvoke(new Action <Tile, ImageSource>((t, i) => t.SetImage(i)), tile, image);
                }
                else
                {
                    tile.SetImage(null);
                }
            }

            Interlocked.Decrement(ref taskCount);
        }
Example #11
0
        private void LoadPendingTiles(Dispatcher dispatcher, TileSource tileSource, string sourceName, bool animateOpacity)
        {
            var  setImageAction  = new Action <Tile, ImageSource>((t, i) => t.SetImageSource(i, animateOpacity));
            var  imageTileSource = tileSource as ImageTileSource;
            Tile tile;

            while (pendingTiles.TryDequeue(out tile))
            {
                byte[]      buffer = null;
                ImageSource image  = null;

                if (imageTileSource != null)
                {
                    image = LoadImage(imageTileSource, tile);
                }
                else
                {
                    var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);

                    if (uri != null)
                    {
                        if (uri.Scheme == "file") // create from FileStream because creating from URI leaves the file open
                        {
                            image = CreateImage(uri.LocalPath);
                        }
                        else
                        {
                            buffer = DownloadImage(uri);
                            image  = CreateImage(buffer);
                        }
                    }
                }

                if (image != null || !tile.HasImageSource) // set null image if tile does not yet have an ImageSource
                {
                    dispatcher.BeginInvoke(setImageAction, tile, image);
                }

                if (image != null && buffer != null && Cache != null && !string.IsNullOrWhiteSpace(sourceName))
                {
                    Cache.Set(TileCache.Key(sourceName, tile), buffer, new CacheItemPolicy {
                        SlidingExpiration = CacheExpiration
                    });
                }
            }

            Interlocked.Decrement(ref threadCount);
        }
        private static async Task LoadCachedTileAsync(Tile tile, TileSource tileSource, string cacheName)
        {
            var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);

            if (uri != null)
            {
                var extension = Path.GetExtension(uri.LocalPath);

                if (string.IsNullOrEmpty(extension) || extension == ".jpeg")
                {
                    extension = ".jpg";
                }

                var cacheKey = string.Format("{0}/{1}/{2}/{3}{4}", cacheName, tile.ZoomLevel, tile.XIndex, tile.Y, extension);

                await LoadCachedTileAsync(tile, uri, cacheKey).ConfigureAwait(false);
            }
        }
        private async Task LoadTileImageAsync(TileSource tileSource, Tile tile)
        {
            tile.Pending = false;

            try
            {
                var imageSource = await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel);

                if (imageSource != null)
                {
                    tile.SetImage(imageSource);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("TileImageLoader: {0}/{1}/{2}: {3}", tile.ZoomLevel, tile.XIndex, tile.Y, ex.Message);
            }
        }
        private async Task LoadCachedTileImageAsync(Tile tile, TileSource tileSource, string sourceName)
        {
            var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);

            if (uri != null)
            {
                var extension = Path.GetExtension(uri.LocalPath);

                if (string.IsNullOrEmpty(extension) || extension == ".jpeg")
                {
                    extension = ".jpg";
                }

                var cacheKey = string.Format(CacheKeyFormat, sourceName, tile.ZoomLevel, tile.XIndex, tile.Y, extension);

                await LoadCachedTileImageAsync(tile, uri, cacheKey);
            }
        }
Example #15
0
        private void GetTiles(List <Tile> tiles, Dispatcher dispatcher, TileSource tileSource, string sourceName, bool animateOpacity, int maxDownloads)
        {
            if (Cache != null && !string.IsNullOrWhiteSpace(sourceName) &&
                !(tileSource is ImageTileSource) && !tileSource.UriFormat.StartsWith("file:"))
            {
                var setImageAction = new Action <Tile, ImageSource>((t, i) => t.SetImageSource(i, animateOpacity));
                var outdatedTiles  = new List <Tile>(tiles.Count);

                foreach (var tile in tiles)
                {
                    var buffer = Cache.Get(TileCache.Key(sourceName, tile)) as byte[];
                    var image  = CreateImage(buffer);

                    if (image == null)
                    {
                        pendingTiles.Enqueue(tile); // not yet cached
                    }
                    else if (CacheUpdateAge > TimeSpan.Zero && TileCache.CreationTime(buffer) + CacheUpdateAge < DateTime.UtcNow)
                    {
                        dispatcher.Invoke(setImageAction, tile, image); // synchronously before enqueuing
                        outdatedTiles.Add(tile);                        // update outdated cache
                    }
                    else
                    {
                        dispatcher.BeginInvoke(setImageAction, tile, image);
                    }
                }

                tiles = outdatedTiles; // enqueue outdated tiles after current tiles
            }

            foreach (var tile in tiles)
            {
                pendingTiles.Enqueue(tile);
            }

            while (threadCount < Math.Min(pendingTiles.Count, maxDownloads))
            {
                Interlocked.Increment(ref threadCount);

                ThreadPool.QueueUserWorkItem(o => LoadPendingTiles(dispatcher, tileSource, sourceName, animateOpacity));
            }
        }
Example #16
0
        private async Task LoadTileImageAsync(Tile tile, TileSource tileSource)
        {
            var tcs = new TaskCompletionSource <object>();

            await tile.Image.Dispatcher.RunAsync(CoreDispatcherPriority.Low, async() =>
            {
                try
                {
                    tile.SetImage(await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel));
                    tcs.SetResult(null);
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            });

            await tcs.Task;
        }
        private async Task LoadPendingTiles(TileQueue tileQueue, TileSource tileSource, string cacheName)
        {
            while (tileQueue.TryDequeue(out var tile))
            {
                try
                {
                    await LoadTile(tile, tileSource, cacheName).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"TileImageLoader: {tile.ZoomLevel}/{tile.XIndex}/{tile.Y}: {ex.Message}");
                }

                if (Progress != null && !tileQueue.IsCanceled)
                {
                    Interlocked.Increment(ref progressLoaded);

                    Progress.Report((double)progressLoaded / progressTotal);
                }
            }
        }
        /// <summary>
        /// Loads all pending tiles from the tiles collection.
        /// If tileSource.UriFormat starts with "http" and cacheName is a non-empty string,
        /// tile images will be cached in the TileImageLoader's Cache - if that is not null.
        /// </summary>
        public Task LoadTiles(IEnumerable <Tile> tiles, TileSource tileSource, string cacheName)
        {
            pendingTiles?.Cancel();

            TileSource = tileSource;

            if (tileSource != null)
            {
                pendingTiles = new TileQueue(tiles);

                var numTasks = Math.Min(pendingTiles.Count, MaxLoadTasks);

                if (numTasks > 0)
                {
                    if (Progress != null)
                    {
                        progressTotal  = pendingTiles.Count;
                        progressLoaded = 0;
                        Progress.Report(0d);
                    }

                    if (Cache == null || tileSource.UriTemplate == null || !tileSource.UriTemplate.StartsWith("http"))
                    {
                        cacheName = null; // no tile caching
                    }

                    return(Task.WhenAll(Enumerable.Range(0, numTasks).Select(
                                            _ => Task.Run(() => LoadPendingTiles(pendingTiles, tileSource, cacheName)))));
                }
            }

            if (Progress != null && progressLoaded < progressTotal)
            {
                Progress.Report(1d);
            }

            return(Task.CompletedTask);
        }
Example #19
0
        private async Task <bool> DownloadTileImageAsync(Tile tile, Uri uri, string cacheKey)
        {
            var success = false;

            try
            {
                using (var response = await TileSource.HttpClient.GetAsync(uri))
                {
                    success = response.IsSuccessStatusCode;

                    if (!success)
                    {
                        Debug.WriteLine("TileImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
                    }
                    else if (TileSource.TileAvailable(response.Headers))
                    {
                        using (var stream = new MemoryStream())
                        {
                            await response.Content.CopyToAsync(stream);

                            stream.Seek(0, SeekOrigin.Begin);

                            await SetTileImageAsync(tile, stream); // create BitmapFrame before caching

                            SetCachedImage(cacheKey, stream, GetExpiration(response));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("TileImageLoader: {0}: {1}", uri, ex.Message);
            }

            return(success);
        }
 private static Task LoadTile(Tile tile, TileSource tileSource)
 {
     return(SetTileImage(tile, () => tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel)));
 }
        private void LoadPendingTiles(Dispatcher dispatcher, TileSource tileSource, string sourceName)
        {
            var imageTileSource = tileSource as ImageTileSource;
            PendingTile pendingTile;

            while (pendingTiles.TryDequeue(out pendingTile))
            {
                var tile = pendingTile.Tile;
                ImageSource image = null;

                if (imageTileSource != null)
                {
                    image = LoadImage(imageTileSource, tile);
                }
                else
                {
                    var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);

                    if (uri != null)
                    {
                        if (!uri.IsAbsoluteUri)
                        {
                            image = LoadImage(uri.OriginalString);
                        }
                        else if (uri.Scheme == "file")
                        {
                            image = LoadImage(uri.LocalPath);
                        }
                        else
                        {
                            image = DownloadImage(uri, CacheKey(sourceName, tile))
                                ?? pendingTile.CachedImage; // use possibly cached image if download failed
                        }
                    }
                }

                if (image != null)
                {
                    dispatcher.BeginInvoke(new Action<Tile, ImageSource>((t, i) => t.SetImage(i)), tile, image);
                }
                else
                {
                    tile.SetImage(null);
                }
            }

            Interlocked.Decrement(ref taskCount);
        }
Example #22
0
        private static async Task LoadTileAsync(Tile tile, TileSource tileSource)
        {
            var image = await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel).ConfigureAwait(false);

            await tile.Image.Dispatcher.InvokeAsync(() => tile.SetImage(image));
        }
 private static string TileKey(TileSource tileSource, Tile tile)
 {
     return string.Format("{0:X}/{1:X}/{2:X}/{3:X}", tileSource.GetHashCode(), tile.ZoomLevel, tile.XIndex, tile.Y);
 }
        private async Task LoadPendingTiles(TileSource tileSource, string sourceName)
        {
            PendingTile pendingTile;

            while (pendingTiles.TryDequeue(out pendingTile))
            {
                var tile = pendingTile.Tile;
                var uri = pendingTile.Uri;
                var image = pendingTile.Image;
                var extension = Path.GetExtension(uri.LocalPath);

                if (string.IsNullOrEmpty(extension) || extension == ".jpeg")
                {
                    extension = ".jpg";
                }

                var cacheKey = string.Format(@"{0}\{1}\{2}\{3}{4}", sourceName, tile.ZoomLevel, tile.XIndex, tile.Y, extension);
                var cacheItem = await Cache.GetAsync(cacheKey);
                var loaded = false;

                if (cacheItem == null || cacheItem.Expires <= DateTime.UtcNow)
                {
                    loaded = await DownloadImage(tile, image, uri, cacheKey);
                }

                if (!loaded && cacheItem != null && cacheItem.Buffer != null)
                {
                    using (var stream = new InMemoryRandomAccessStream())
                    {
                        await stream.WriteAsync(cacheItem.Buffer);
                        await stream.FlushAsync();
                        stream.Seek(0);

                        await LoadImageFromStream(tile, image, stream);
                    }
                }
            }

            Interlocked.Decrement(ref taskCount);
        }
 private async Task LoadTileImageAsync(Tile tile, TileSource tileSource)
 {
     SetTileImage(tile, await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel));
 }
Example #26
0
        private void GetTiles(List <Tile> tiles, Dispatcher dispatcher, TileSource tileSource,
                              string sourceName, int maxDownloads, bool animateOpacity)
        {
            var imageTileSource = tileSource as ImageTileSource;

            if (imageTileSource != null)
            {
                if (!imageTileSource.CanLoadAsync) // call LoadImage in UI thread
                {
                    var setImageAction = new Action <Tile, ImageTileSource>((t, ts) => t.SetImageSource(LoadImage(ts, t), animateOpacity));

                    foreach (var tile in tiles)
                    {
                        dispatcher.BeginInvoke(setImageAction, DispatcherPriority.Render, tile, imageTileSource);
                    }

                    return;
                }
            }
            else if (!tileSource.UriFormat.StartsWith("file:")) // load local image files asynchronously, without caching
            {
                if (Cache == null || string.IsNullOrWhiteSpace(sourceName))
                {
                    // no caching here: use default asynchronous downloading and caching done by WPF

                    var setImageAction = new Action <Tile, TileSource>((t, ts) => t.SetImageSource(CreateImage(ts, t), animateOpacity));

                    foreach (var tile in tiles)
                    {
                        dispatcher.BeginInvoke(setImageAction, DispatcherPriority.Render, tile, tileSource);
                    }

                    return;
                }
                else
                {
                    var setImageAction = new Action <Tile, ImageSource>((t, i) => t.SetImageSource(i, animateOpacity));
                    var outdatedTiles  = new List <Tile>(tiles.Count);

                    foreach (var tile in tiles)
                    {
                        var key    = GetCacheKey(sourceName, tile);
                        var buffer = Cache.Get(key) as byte[];
                        var image  = CreateImage(buffer);

                        if (image != null)
                        {
                            var creationTime = BitConverter.ToInt64(buffer, 0);

                            if (DateTime.FromBinary(creationTime) + CacheUpdateAge < DateTime.UtcNow)
                            {
                                dispatcher.Invoke(setImageAction, DispatcherPriority.Render, tile, image); // synchronously before enqueuing
                                outdatedTiles.Add(tile);                                                   // update outdated cache
                            }
                            else
                            {
                                dispatcher.BeginInvoke(setImageAction, DispatcherPriority.Render, tile, image);
                            }
                        }
                        else
                        {
                            pendingTiles.Enqueue(tile); // not yet cached
                        }
                    }

                    tiles = outdatedTiles; // enqueue outdated tiles at last
                }
            }

            foreach (var tile in tiles)
            {
                pendingTiles.Enqueue(tile);
            }

            while (threadCount < Math.Min(pendingTiles.Count, maxDownloads))
            {
                Interlocked.Increment(ref threadCount);

                ThreadPool.QueueUserWorkItem(o => LoadPendingTiles(dispatcher, tileSource, sourceName, animateOpacity));
            }
        }
Example #27
0
 private static string TileKey(TileSource tileSource, Tile tile)
 {
     return(string.Format("{0:X}/{1:X}/{2:X}/{3:X}", tileSource.GetHashCode(), tile.ZoomLevel, tile.XIndex, tile.Y));
 }
        private void GetTiles(List<Tile> tiles, Dispatcher dispatcher, TileSource tileSource, string sourceName, bool animateOpacity, int maxDownloads)
        {
            if (Cache != null && !string.IsNullOrWhiteSpace(sourceName) &&
                !(tileSource is ImageTileSource) && !tileSource.UriFormat.StartsWith("file:"))
            {
                var setImageAction = new Action<Tile, ImageSource>((t, i) => t.SetImageSource(i, animateOpacity));
                var outdatedTiles = new List<Tile>(tiles.Count);

                foreach (var tile in tiles)
                {
                    var buffer = Cache.Get(TileCache.Key(sourceName, tile)) as byte[];
                    var image = CreateImage(buffer);

                    if (image == null)
                    {
                        pendingTiles.Enqueue(tile); // not yet cached
                    }
                    else if (CacheUpdateAge > TimeSpan.Zero && TileCache.CreationTime(buffer) + CacheUpdateAge < DateTime.UtcNow)
                    {
                        dispatcher.Invoke(setImageAction, tile, image); // synchronously before enqueuing
                        outdatedTiles.Add(tile); // update outdated cache
                    }
                    else
                    {
                        dispatcher.BeginInvoke(setImageAction, tile, image);
                    }
                }

                tiles = outdatedTiles; // enqueue outdated tiles after current tiles
            }

            foreach (var tile in tiles)
            {
                pendingTiles.Enqueue(tile);
            }

            while (threadCount < Math.Min(pendingTiles.Count, maxDownloads))
            {
                Interlocked.Increment(ref threadCount);

                ThreadPool.QueueUserWorkItem(o => LoadPendingTiles(dispatcher, tileSource, sourceName, animateOpacity));
            }
        }
        private void GetTiles(IEnumerable<Tile> tiles, Dispatcher dispatcher, TileSource tileSource, string sourceName, int maxDownloads)
        {
            var useCache = Cache != null
                && !string.IsNullOrEmpty(sourceName)
                && !(tileSource is ImageTileSource)
                && !tileSource.UriFormat.StartsWith("file:");

            foreach (var tile in tiles)
            {
                BitmapSource cachedImage = null;

                if (useCache && GetCachedImage(CacheKey(sourceName, tile), out cachedImage))
                {
                    dispatcher.BeginInvoke(new Action<Tile, ImageSource>((t, i) => t.SetImage(i)), tile, cachedImage);
                }
                else
                {
                    pendingTiles.Enqueue(new PendingTile(tile, cachedImage));
                }
            }

            var newTaskCount = Math.Min(pendingTiles.Count, maxDownloads) - taskCount;

            while (newTaskCount-- > 0)
            {
                Interlocked.Increment(ref taskCount);

                Task.Run(() => LoadPendingTiles(dispatcher, tileSource, sourceName));
            }
        }
        private void LoadPendingTiles(Dispatcher dispatcher, TileSource tileSource, string sourceName, bool animateOpacity)
        {
            var setImageAction = new Action<Tile, ImageSource>((t, i) => t.SetImageSource(i, animateOpacity));
            var imageTileSource = tileSource as ImageTileSource;
            Tile tile;

            while (pendingTiles.TryDequeue(out tile))
            {
                byte[] buffer = null;
                ImageSource image = null;

                if (imageTileSource != null)
                {
                    image = LoadImage(imageTileSource, tile);
                }
                else
                {
                    var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel, tile.Rotation);

                    if (uri != null)
                    {
                        if (uri.Scheme == "file") // create from FileStream because creating from URI leaves the file open
                        {
                            image = CreateImage(uri.LocalPath);
                        }
                        else
                        {
                            buffer = DownloadImage(uri);
                            image = CreateImage(buffer);
                        }
                    }
                }

                if (image != null || !tile.HasImageSource) // set null image if tile does not yet have an ImageSource
                {
                    dispatcher.BeginInvoke(setImageAction, tile, image);
                }

                if (image != null && buffer != null && Cache != null && !string.IsNullOrWhiteSpace(sourceName))
                {
                    Cache.Set(TileCache.Key(sourceName, tile), buffer, new CacheItemPolicy { SlidingExpiration = CacheExpiration });
                }
            }

            Interlocked.Decrement(ref threadCount);
        }