From 220597ab3114c87c14baa4f9d260f4828b457b87 Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Wed, 20 Aug 2025 19:50:22 +0200 Subject: [PATCH] Image loading with cancellation --- MapControl/Shared/MapImageLayer.cs | 3 +++ MapControl/Shared/MapTileLayerBase.cs | 2 +- MapControl/Shared/TileImageLoader.cs | 5 ++++- MapControl/UWP/TileImageLoader.UWP.cs | 6 +++--- MapControl/WinUI/TileImageLoader.WinUI.cs | 6 +++--- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/MapControl/Shared/MapImageLayer.cs b/MapControl/Shared/MapImageLayer.cs index 4abd5762..518a0a60 100644 --- a/MapControl/Shared/MapImageLayer.cs +++ b/MapControl/Shared/MapImageLayer.cs @@ -171,8 +171,11 @@ namespace MapControl protected async Task UpdateImageAsync() { updateTimer.Stop(); + cancellationTokenSource?.Cancel(); + ClearValue(LoadingProgressProperty); + if (ParentMap != null && ParentMap.ActualWidth > 0d && ParentMap.ActualHeight > 0d) { var width = ParentMap.ActualWidth * RelativeImageSize; diff --git a/MapControl/Shared/MapTileLayerBase.cs b/MapControl/Shared/MapTileLayerBase.cs index fb329977..40d5437c 100644 --- a/MapControl/Shared/MapTileLayerBase.cs +++ b/MapControl/Shared/MapTileLayerBase.cs @@ -61,8 +61,8 @@ namespace MapControl private readonly Progress loadingProgress; private readonly DispatcherTimer updateTimer; - private ITileImageLoader tileImageLoader; private CancellationTokenSource cancellationTokenSource; + private ITileImageLoader tileImageLoader; private MapBase parentMap; protected MapTileLayerBase() diff --git a/MapControl/Shared/TileImageLoader.cs b/MapControl/Shared/TileImageLoader.cs index f06241d0..b7b501db 100644 --- a/MapControl/Shared/TileImageLoader.cs +++ b/MapControl/Shared/TileImageLoader.cs @@ -7,6 +7,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security.Policy; using System.Threading; using System.Threading.Tasks; #if WPF @@ -102,10 +103,12 @@ namespace MapControl progress?.Report((double)(tileCount - pendingTiles.Count) / tileCount); - var requestCancellationToken = RequestCancellationEnabled ? cancellationToken : CancellationToken.None; + Logger?.LogTrace("[{thread}] Loading tile image {zoom}/{column}/{row}", Environment.CurrentManagedThreadId, tile.ZoomLevel, tile.Column, tile.Row); try { + var requestCancellationToken = RequestCancellationEnabled ? cancellationToken : CancellationToken.None; + await LoadTileImage(tile, tileSource, cacheName, requestCancellationToken).ConfigureAwait(false); } catch (Exception ex) diff --git a/MapControl/UWP/TileImageLoader.UWP.cs b/MapControl/UWP/TileImageLoader.UWP.cs index f281fc93..f3c8d0bc 100644 --- a/MapControl/UWP/TileImageLoader.UWP.cs +++ b/MapControl/UWP/TileImageLoader.UWP.cs @@ -17,16 +17,16 @@ namespace MapControl try { var image = await loadImageFunc(); - - tcs.TrySetResult(null); // tcs.Task has completed when image is loaded if (cancellationToken.IsCancellationRequested) { tile.IsPending = true; + tcs.TrySetCanceled(cancellationToken); } else { tile.SetImageSource(image); + tcs.TrySetResult(null); } } catch (Exception ex) @@ -37,7 +37,7 @@ namespace MapControl if (!await tile.Image.Dispatcher.TryRunAsync(CoreDispatcherPriority.Low, LoadTileImage)) { - tcs.TrySetCanceled(cancellationToken); + tcs.TrySetCanceled(CancellationToken.None); } await tcs.Task; diff --git a/MapControl/WinUI/TileImageLoader.WinUI.cs b/MapControl/WinUI/TileImageLoader.WinUI.cs index 75542a27..ea40bff6 100644 --- a/MapControl/WinUI/TileImageLoader.WinUI.cs +++ b/MapControl/WinUI/TileImageLoader.WinUI.cs @@ -18,15 +18,15 @@ namespace MapControl { var image = await loadImageFunc(); - tcs.TrySetResult(); // tcs.Task has completed when image is loaded - if (cancellationToken.IsCancellationRequested) { tile.IsPending = true; + tcs.TrySetCanceled(cancellationToken); } else { tile.SetImageSource(image); + tcs.TrySetResult(); } } catch (Exception ex) @@ -37,7 +37,7 @@ namespace MapControl if (!tile.Image.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, LoadTileImage)) { - tcs.TrySetCanceled(cancellationToken); + tcs.TrySetCanceled(CancellationToken.None); } return tcs.Task;