Refactored TileImageLoader

This commit is contained in:
Clemens 2021-11-22 23:07:07 +01:00
parent c78e72f735
commit d4e851e0f7
4 changed files with 30 additions and 24 deletions

View file

@ -49,13 +49,20 @@ namespace MapControl
/// </summary> /// </summary>
public Task LoadTiles(IEnumerable<Tile> tiles, TileSource tileSource, string cacheName) public Task LoadTiles(IEnumerable<Tile> tiles, TileSource tileSource, string cacheName)
{ {
pendingTiles?.Clear(); // stop download from current stack pendingTiles?.Clear(); // stop processing the current queue
pendingTiles = new ConcurrentStack<Tile>(tiles.Where(tile => tile.Pending).Reverse());
TileSource = tileSource; TileSource = tileSource;
if (tileSource == null || pendingTiles.IsEmpty) if (tileSource == null)
{
return Task.CompletedTask;
}
pendingTiles = new ConcurrentStack<Tile>(tiles.Where(tile => tile.Pending).Reverse());
var numTasks = Math.Min(pendingTiles.Count, MaxLoadTasks);
if (numTasks < 1)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -65,14 +72,13 @@ namespace MapControl
cacheName = null; // no tile caching cacheName = null; // no tile caching
} }
var tasks = Enumerable var tasks = Enumerable.Range(0, numTasks)
.Range(0, Math.Min(pendingTiles.Count, MaxLoadTasks)) .Select(_ => Task.Run(() => LoadPendingTiles(pendingTiles, tileSource, cacheName)));
.Select(_ => Task.Run(() => LoadPendingTilesAsync(pendingTiles, tileSource, cacheName)));
return Task.WhenAll(tasks); return Task.WhenAll(tasks);
} }
private static async Task LoadPendingTilesAsync(ConcurrentStack<Tile> pendingTiles, TileSource tileSource, string cacheName) private static async Task LoadPendingTiles(ConcurrentStack<Tile> pendingTiles, TileSource tileSource, string cacheName)
{ {
while (pendingTiles.TryPop(out var tile)) while (pendingTiles.TryPop(out var tile))
{ {
@ -80,7 +86,7 @@ namespace MapControl
try try
{ {
await LoadTileAsync(tile, tileSource, cacheName).ConfigureAwait(false); await LoadTile(tile, tileSource, cacheName).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -89,11 +95,11 @@ namespace MapControl
} }
} }
private static Task LoadTileAsync(Tile tile, TileSource tileSource, string cacheName) private static Task LoadTile(Tile tile, TileSource tileSource, string cacheName)
{ {
if (string.IsNullOrEmpty(cacheName)) if (string.IsNullOrEmpty(cacheName))
{ {
return LoadTileAsync(tile, tileSource); return LoadTile(tile, tileSource);
} }
var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel); var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);
@ -113,7 +119,7 @@ namespace MapControl
var cacheKey = string.Format(CultureInfo.InvariantCulture, var cacheKey = string.Format(CultureInfo.InvariantCulture,
"{0}/{1}/{2}/{3}{4}", cacheName, tile.ZoomLevel, tile.XIndex, tile.Y, extension); "{0}/{1}/{2}/{3}{4}", cacheName, tile.ZoomLevel, tile.XIndex, tile.Y, extension);
return LoadCachedTileAsync(tile, uri, cacheKey); return LoadCachedTile(tile, uri, cacheKey);
} }
private static DateTime GetExpiration(TimeSpan? maxAge) private static DateTime GetExpiration(TimeSpan? maxAge)

View file

@ -36,7 +36,7 @@ namespace MapControl
public static Caching.IImageCache Cache { get; set; } public static Caching.IImageCache Cache { get; set; }
private static async Task LoadCachedTileAsync(Tile tile, Uri uri, string cacheKey) private static async Task LoadCachedTile(Tile tile, Uri uri, string cacheKey)
{ {
var cacheItem = await Cache.GetAsync(cacheKey).ConfigureAwait(false); var cacheItem = await Cache.GetAsync(cacheKey).ConfigureAwait(false);
var buffer = cacheItem?.Item1; var buffer = cacheItem?.Item1;
@ -56,16 +56,16 @@ namespace MapControl
if (buffer != null && buffer.Length > 0) if (buffer != null && buffer.Length > 0)
{ {
await SetTileImageAsync(tile, () => ImageLoader.LoadImageAsync(buffer)).ConfigureAwait(false); await SetTileImage(tile, () => ImageLoader.LoadImageAsync(buffer)).ConfigureAwait(false);
} }
} }
private static Task LoadTileAsync(Tile tile, TileSource tileSource) private static Task LoadTile(Tile tile, TileSource tileSource)
{ {
return SetTileImageAsync(tile, () => tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel)); return SetTileImage(tile, () => tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel));
} }
public static async Task SetTileImageAsync(Tile tile, Func<Task<ImageSource>> loadImageFunc) private static async Task SetTileImage(Tile tile, Func<Task<ImageSource>> loadImageFunc)
{ {
var tcs = new TaskCompletionSource<object>(); var tcs = new TaskCompletionSource<object>();

View file

@ -25,7 +25,7 @@ namespace MapControl
public static ObjectCache Cache { get; set; } = MemoryCache.Default; public static ObjectCache Cache { get; set; } = MemoryCache.Default;
private static async Task LoadCachedTileAsync(Tile tile, Uri uri, string cacheKey) private static async Task LoadCachedTile(Tile tile, Uri uri, string cacheKey)
{ {
var cacheItem = Cache.Get(cacheKey) as Tuple<byte[], DateTime>; var cacheItem = Cache.Get(cacheKey) as Tuple<byte[], DateTime>;
var buffer = cacheItem?.Item1; var buffer = cacheItem?.Item1;
@ -53,7 +53,7 @@ namespace MapControl
} }
} }
private static async Task LoadTileAsync(Tile tile, TileSource tileSource) private static async Task LoadTile(Tile tile, TileSource tileSource)
{ {
var image = await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel).ConfigureAwait(false); var image = await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel).ConfigureAwait(false);

View file

@ -36,7 +36,7 @@ namespace MapControl
public static Caching.IImageCache Cache { get; set; } public static Caching.IImageCache Cache { get; set; }
private static async Task LoadCachedTileAsync(Tile tile, Uri uri, string cacheKey) private static async Task LoadCachedTile(Tile tile, Uri uri, string cacheKey)
{ {
var cacheItem = await Cache.GetAsync(cacheKey).ConfigureAwait(false); var cacheItem = await Cache.GetAsync(cacheKey).ConfigureAwait(false);
var buffer = cacheItem?.Item1; var buffer = cacheItem?.Item1;
@ -56,16 +56,16 @@ namespace MapControl
if (buffer != null && buffer.Length > 0) if (buffer != null && buffer.Length > 0)
{ {
await SetTileImageAsync(tile, () => ImageLoader.LoadImageAsync(buffer)).ConfigureAwait(false); await SetTileImage(tile, () => ImageLoader.LoadImageAsync(buffer)).ConfigureAwait(false);
} }
} }
private static Task LoadTileAsync(Tile tile, TileSource tileSource) private static Task LoadTile(Tile tile, TileSource tileSource)
{ {
return SetTileImageAsync(tile, () => tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel)); return SetTileImage(tile, () => tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel));
} }
public static Task SetTileImageAsync(Tile tile, Func<Task<ImageSource>> loadImageFunc) private static Task SetTileImage(Tile tile, Func<Task<ImageSource>> loadImageFunc)
{ {
var tcs = new TaskCompletionSource(); var tcs = new TaskCompletionSource();