diff --git a/MapControl/Map.cs b/MapControl/Map.cs index 2ef0d6e7..1d03449e 100644 --- a/MapControl/Map.cs +++ b/MapControl/Map.cs @@ -378,8 +378,15 @@ namespace MapControl { if (translation.X != 0d || translation.Y != 0d) { - ResetTransformOrigin(); - Center = ViewportPointToLocation(viewportOrigin - translation); + if (transformOrigin != null) + { + viewportOrigin += translation; + UpdateViewTransform(); + } + else + { + Center = ViewportPointToLocation(viewportOrigin - translation); + } } } @@ -566,6 +573,7 @@ namespace MapControl From = Center, To = targetCenter, Duration = TimeSpan.FromSeconds(0.5), + FillBehavior = FillBehavior.Stop, EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut } }; @@ -577,7 +585,7 @@ namespace MapControl private void CenterAnimationCompleted(object sender, EventArgs eventArgs) { Center = TargetCenter; - BeginAnimation(CenterProperty, null); + centerAnimation.Completed -= CenterAnimationCompleted; centerAnimation = null; } @@ -615,6 +623,7 @@ namespace MapControl From = ZoomLevel, To = targetZoomLevel, Duration = TimeSpan.FromSeconds(0.5), + FillBehavior = FillBehavior.Stop, EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut } }; @@ -626,7 +635,7 @@ namespace MapControl private void ZoomLevelAnimationCompleted(object sender, EventArgs eventArgs) { ZoomLevel = TargetZoomLevel; - BeginAnimation(ZoomLevelProperty, null); + zoomLevelAnimation.Completed -= ZoomLevelAnimationCompleted; zoomLevelAnimation = null; ResetTransformOrigin(); } @@ -674,6 +683,7 @@ namespace MapControl From = Heading, By = delta, Duration = TimeSpan.FromSeconds(0.5), + FillBehavior = FillBehavior.Stop, EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut } }; @@ -685,7 +695,7 @@ namespace MapControl private void HeadingAnimationCompleted(object sender, EventArgs eventArgs) { Heading = TargetHeading; - BeginAnimation(HeadingProperty, null); + headingAnimation.Completed -= HeadingAnimationCompleted; headingAnimation = null; } diff --git a/MapControl/TileImageLoader.cs b/MapControl/TileImageLoader.cs index 4f4008f3..00648fbc 100644 --- a/MapControl/TileImageLoader.cs +++ b/MapControl/TileImageLoader.cs @@ -3,6 +3,7 @@ // Licensed under the Microsoft Public License (Ms-PL) using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; @@ -35,8 +36,7 @@ namespace MapControl } private readonly TileLayer tileLayer; - private readonly Queue pendingTiles = new Queue(); - private readonly HashSet currentRequests = new HashSet(); + private readonly ConcurrentQueue pendingTiles = new ConcurrentQueue(); /// /// The ObjectCache used to cache tile images. @@ -121,18 +121,8 @@ namespace MapControl internal void CancelGetTiles() { - lock (pendingTiles) - { - pendingTiles.Clear(); - } - - lock (currentRequests) - { - foreach (HttpWebRequest request in currentRequests) - { - request.Abort(); - } - } + Tile tile; + while (pendingTiles.TryDequeue(out tile)) ; // no Clear method } private void BeginGetTilesAsync(object newTilesList) @@ -150,67 +140,53 @@ namespace MapControl } else { - lock (pendingTiles) + if (Cache == null) { - if (Cache == null) - { - newTiles.ForEach(tile => pendingTiles.Enqueue(tile)); - } - else - { - List outdatedTiles = new List(newTiles.Count); + newTiles.ForEach(tile => pendingTiles.Enqueue(tile)); + } + else + { + List outdatedTiles = new List(newTiles.Count); - newTiles.ForEach(tile => + newTiles.ForEach(tile => + { + string key = CacheKey(tile); + CachedImage cachedImage = Cache.Get(key) as CachedImage; + + if (cachedImage == null) { - string key = CacheKey(tile); - CachedImage cachedImage = Cache.Get(key) as CachedImage; + pendingTiles.Enqueue(tile); + } + else if (!CreateTileImage(tile, cachedImage.ImageBuffer)) + { + // got corrupted buffer from cache + Cache.Remove(key); + pendingTiles.Enqueue(tile); + } + else if (cachedImage.CreationTime + CacheUpdateAge < DateTime.UtcNow) + { + // update cached image + outdatedTiles.Add(tile); + } + }); - if (cachedImage == null) - { - pendingTiles.Enqueue(tile); - } - else if (!CreateTileImage(tile, cachedImage.ImageBuffer)) - { - // got corrupted buffer from cache - Cache.Remove(key); - pendingTiles.Enqueue(tile); - } - else if (cachedImage.CreationTime + CacheUpdateAge < DateTime.UtcNow) - { - // update cached image - outdatedTiles.Add(tile); - } - }); + outdatedTiles.ForEach(tile => pendingTiles.Enqueue(tile)); + } - outdatedTiles.ForEach(tile => pendingTiles.Enqueue(tile)); - } + int numDownloads = Math.Min(pendingTiles.Count, tileLayer.MaxParallelDownloads); - int numDownloads = Math.Min(pendingTiles.Count, tileLayer.MaxParallelDownloads); - - while (--numDownloads >= 0) - { - ThreadPool.QueueUserWorkItem(DownloadTiles); - } + while (--numDownloads >= 0) + { + ThreadPool.QueueUserWorkItem(DownloadTiles); } } } private void DownloadTiles(object o) { - while (pendingTiles.Count > 0) + Tile tile; + while (pendingTiles.TryDequeue(out tile)) { - Tile tile; - - lock (pendingTiles) - { - if (pendingTiles.Count == 0) - { - break; - } - - tile = pendingTiles.Dequeue(); - } - tile.Uri = tileLayer.TileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel); byte[] imageBuffer = DownloadImage(tile); @@ -241,11 +217,6 @@ namespace MapControl request.UserAgent = typeof(TileImageLoader).ToString(); request.KeepAlive = true; - lock (currentRequests) - { - currentRequests.Add(request); - } - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream responseStream = response.GetResponseStream()) { @@ -275,10 +246,6 @@ namespace MapControl { TraceInformation("{0} - {1}", tile.Uri, ((HttpWebResponse)ex.Response).StatusCode); } - else if (ex.Status == WebExceptionStatus.RequestCanceled) // by HttpWebRequest.Abort in CancelGetTiles - { - TraceInformation("{0} - {1}", tile.Uri, ex.Status); - } else { TraceWarning("{0} - {1}", tile.Uri, ex.Status); @@ -289,14 +256,6 @@ namespace MapControl TraceWarning("{0} - {1}", tile.Uri, ex.Message); } - if (request != null) - { - lock (currentRequests) - { - currentRequests.Remove(request); - } - } - return buffer; }