mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 4.12.2 Dropped Windows.Web.Http.HtpClient
This commit is contained in:
parent
014f57ee1a
commit
9c55597a16
|
|
@ -3,14 +3,17 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
#if WINDOWS_UWP
|
||||
using Windows.Web.Http;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using System.Net.Http;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
#endif
|
||||
|
|
@ -36,7 +39,26 @@ namespace MapControl
|
|||
}
|
||||
else if (uri.Scheme == "http" || uri.Scheme == "https")
|
||||
{
|
||||
image = await LoadHttpImageAsync(uri);
|
||||
using (var response = await HttpClient.GetAsync(uri))
|
||||
{
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
if (ImageAvailable(response.Headers))
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
await response.Content.CopyToAsync(stream);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
image = await LoadImageAsync(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -51,23 +73,50 @@ namespace MapControl
|
|||
return image;
|
||||
}
|
||||
|
||||
private static async Task<ImageSource> LoadHttpImageAsync(Uri uri)
|
||||
internal class ImageStream : MemoryStream
|
||||
{
|
||||
ImageSource image = null;
|
||||
public TimeSpan? MaxAge { get; set; }
|
||||
}
|
||||
|
||||
using (var response = await HttpClient.GetAsync(uri))
|
||||
internal static async Task<ImageStream> LoadImageStreamAsync(Uri uri)
|
||||
{
|
||||
if (!response.IsSuccessStatusCode)
|
||||
ImageStream stream = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var response = await HttpClient.GetAsync(uri).ConfigureAwait(false))
|
||||
{
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
stream = new ImageStream();
|
||||
|
||||
if (ImageAvailable(response.Headers))
|
||||
{
|
||||
await response.Content.CopyToAsync(stream).ConfigureAwait(false);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
stream.MaxAge = response.Headers.CacheControl?.MaxAge;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
|
||||
}
|
||||
else if (ImageAvailable(response.Headers))
|
||||
{
|
||||
image = await LoadImageAsync(response.Content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("ImageLoader: {0}: {1}", uri, ex.Message);
|
||||
}
|
||||
|
||||
return image;
|
||||
return stream;
|
||||
}
|
||||
|
||||
private static bool ImageAvailable(HttpResponseHeaders responseHeaders)
|
||||
{
|
||||
IEnumerable<string> tileInfo;
|
||||
|
||||
return !responseHeaders.TryGetValues("X-VE-Tile-Info", out tileInfo) || !tileInfo.Contains("no-tile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,6 +66,9 @@ namespace MapControl
|
|||
public static readonly DependencyProperty MaxZoomLevelProperty = DependencyProperty.Register(
|
||||
nameof(MaxZoomLevel), typeof(int), typeof(MapTileLayer), new PropertyMetadata(18));
|
||||
|
||||
public static readonly DependencyProperty MaxBackgroundZoomLevelsProperty = DependencyProperty.Register(
|
||||
nameof(MaxBackgroundZoomLevels), typeof(int), typeof(MapTileLayer), new PropertyMetadata(8));
|
||||
|
||||
public static readonly DependencyProperty UpdateIntervalProperty = DependencyProperty.Register(
|
||||
nameof(UpdateInterval), typeof(TimeSpan), typeof(MapTileLayer),
|
||||
new PropertyMetadata(TimeSpan.FromSeconds(0.2), (o, e) => ((MapTileLayer)o).updateTimer.Interval = (TimeSpan)e.NewValue));
|
||||
|
|
@ -142,7 +145,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum zoom level supported by the MapTileLayer.
|
||||
/// Minimum zoom level supported by the MapTileLayer. Default value is 0.
|
||||
/// </summary>
|
||||
public int MinZoomLevel
|
||||
{
|
||||
|
|
@ -151,7 +154,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum zoom level supported by the MapTileLayer.
|
||||
/// Maximum zoom level supported by the MapTileLayer. Default value is 18.
|
||||
/// </summary>
|
||||
public int MaxZoomLevel
|
||||
{
|
||||
|
|
@ -159,6 +162,16 @@ namespace MapControl
|
|||
set { SetValue(MaxZoomLevelProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of background tile levels. Default value is 8.
|
||||
/// Applies only to a MapTileLayer that is the MapLayer of its ParentMap.
|
||||
/// </summary>
|
||||
public int MaxBackgroundZoomLevels
|
||||
{
|
||||
get { return (int)GetValue(MaxBackgroundZoomLevelsProperty); }
|
||||
set { SetValue(MaxBackgroundZoomLevelsProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time interval between tile updates.
|
||||
/// </summary>
|
||||
|
|
@ -342,11 +355,14 @@ namespace MapControl
|
|||
if (parentMap != null && TileGrid != null && TileSource != null)
|
||||
{
|
||||
var maxZoomLevel = Math.Min(TileGrid.ZoomLevel, MaxZoomLevel);
|
||||
var minZoomLevel = MinZoomLevel;
|
||||
|
||||
if (minZoomLevel < maxZoomLevel && parentMap.MapLayer != this)
|
||||
if (maxZoomLevel >= MinZoomLevel)
|
||||
{
|
||||
minZoomLevel = maxZoomLevel; // do not load lower level tiles if this is note a "base" layer
|
||||
var minZoomLevel = maxZoomLevel;
|
||||
|
||||
if (this == parentMap.MapLayer) // load background tiles
|
||||
{
|
||||
minZoomLevel = Math.Max(TileGrid.ZoomLevel - MaxBackgroundZoomLevels, MinZoomLevel);
|
||||
}
|
||||
|
||||
for (var z = minZoomLevel; z <= maxZoomLevel; z++)
|
||||
|
|
@ -381,6 +397,7 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tiles = newTiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -45,19 +47,39 @@ namespace MapControl
|
|||
public static string CacheKeyFormat { get; set; } = "{0}/{1}/{2}/{3}{4}";
|
||||
|
||||
|
||||
public class TileQueue : ConcurrentStack<Tile>
|
||||
{
|
||||
public void Enqueue(IEnumerable<Tile> tiles)
|
||||
{
|
||||
PushRange(tiles.Reverse().ToArray());
|
||||
}
|
||||
|
||||
public bool TryDequeue(out Tile tile)
|
||||
{
|
||||
return TryPop(out tile);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly TileQueue tileQueue = new TileQueue();
|
||||
private Func<Tile, Task> loadTileImage;
|
||||
private int taskCount;
|
||||
|
||||
/// <summary>
|
||||
/// Loads all pending tiles from the tiles collection in up to MaxLoadTasks parallel Tasks.
|
||||
/// 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.
|
||||
/// tile images will be cached in the TileImageLoader's Cache (if it's not null).
|
||||
/// </summary>
|
||||
public void LoadTilesAsync(IEnumerable<Tile> tiles, TileSource tileSource, string sourceName)
|
||||
{
|
||||
tileQueue.Clear();
|
||||
|
||||
if (tileSource != null)
|
||||
{
|
||||
SetLoadTileImageFunction(tileSource, sourceName);
|
||||
|
||||
tiles = tiles.Where(tile => tile.Pending);
|
||||
|
||||
if (tiles.Any())
|
||||
{
|
||||
tileQueue.Enqueue(tiles);
|
||||
|
||||
|
|
@ -65,25 +87,29 @@ namespace MapControl
|
|||
|
||||
if (newTasks > 0)
|
||||
{
|
||||
var loadTasks = Enumerable.Range(0, newTasks).Select(n => LoadTilesFromQueueAsync());
|
||||
|
||||
Interlocked.Add(ref taskCount, newTasks);
|
||||
|
||||
while (--newTasks >= 0)
|
||||
{
|
||||
Task.Run(() => LoadTilesFromQueueAsync(tileSource, sourceName));
|
||||
Task.WhenAll(loadTasks); // not awaited
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadTilesFromQueueAsync(TileSource tileSource, string sourceName)
|
||||
private async Task LoadTilesFromQueueAsync()
|
||||
{
|
||||
Tile tile;
|
||||
|
||||
while (tileQueue.TryDequeue(out tile))
|
||||
{
|
||||
tile.Pending = false;
|
||||
|
||||
try
|
||||
{
|
||||
await LoadTileImageAsync(tile, tileSource, sourceName).ConfigureAwait(false);
|
||||
Debug.WriteLine("TileImageLoader: loading {0}/{1}/{2} in thread {3}", tile.ZoomLevel, tile.XIndex, tile.Y, Environment.CurrentManagedThreadId);
|
||||
|
||||
await loadTileImage(tile).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -94,12 +120,22 @@ namespace MapControl
|
|||
Interlocked.Decrement(ref taskCount);
|
||||
}
|
||||
|
||||
private static async Task LoadTileImageAsync(Tile tile, TileSource tileSource, string sourceName)
|
||||
private void SetLoadTileImageFunction(TileSource tileSource, string sourceName)
|
||||
{
|
||||
if (Cache != null &&
|
||||
tileSource.UriFormat != null &&
|
||||
tileSource.UriFormat.StartsWith("http") &&
|
||||
!string.IsNullOrEmpty(sourceName))
|
||||
{
|
||||
loadTileImage = tile => LoadTileImageAsync(tile, tileSource, sourceName);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadTileImage = tile => LoadTileImageAsync(tile, tileSource);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task LoadTileImageAsync(Tile tile, TileSource tileSource, string sourceName)
|
||||
{
|
||||
var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);
|
||||
|
||||
|
|
@ -117,11 +153,6 @@ namespace MapControl
|
|||
await LoadCachedTileImageAsync(tile, uri, cacheKey).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await LoadTileImageAsync(tile, tileSource).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static DateTime GetExpiration(TimeSpan? maxAge)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2019 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class TileQueue : ConcurrentStack<Tile>
|
||||
{
|
||||
public void Enqueue(IEnumerable<Tile> tiles)
|
||||
{
|
||||
tiles = tiles.Where(tile => tile.Pending);
|
||||
|
||||
if (tiles.Any())
|
||||
{
|
||||
PushRange(tiles.Reverse().ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryDequeue(out Tile tile)
|
||||
{
|
||||
var success = TryPop(out tile);
|
||||
|
||||
if (success)
|
||||
{
|
||||
tile.Pending = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -11,13 +10,16 @@ using Windows.Storage;
|
|||
using Windows.Storage.Streams;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
using Windows.Web.Http;
|
||||
using Windows.Web.Http.Headers;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public static partial class ImageLoader
|
||||
{
|
||||
public static Task<ImageSource> LoadImageAsync(Stream stream)
|
||||
{
|
||||
return LoadImageAsync(stream.AsRandomAccessStream());
|
||||
}
|
||||
|
||||
public static async Task<ImageSource> LoadImageAsync(IRandomAccessStream stream)
|
||||
{
|
||||
var image = new BitmapImage();
|
||||
|
|
@ -54,68 +56,5 @@ namespace MapControl
|
|||
|
||||
return image;
|
||||
}
|
||||
|
||||
private static async Task<ImageSource> LoadImageAsync(IHttpContent content)
|
||||
{
|
||||
using (var stream = new InMemoryRandomAccessStream())
|
||||
{
|
||||
await content.WriteToStreamAsync(stream);
|
||||
stream.Seek(0);
|
||||
|
||||
return await LoadImageAsync(stream);
|
||||
}
|
||||
}
|
||||
|
||||
internal class HttpBufferResponse
|
||||
{
|
||||
public readonly IBuffer Buffer;
|
||||
public readonly TimeSpan? MaxAge;
|
||||
|
||||
public HttpBufferResponse(IBuffer buffer, TimeSpan? maxAge)
|
||||
{
|
||||
Buffer = buffer;
|
||||
MaxAge = maxAge;
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task<HttpBufferResponse> LoadHttpBufferAsync(Uri uri)
|
||||
{
|
||||
HttpBufferResponse response = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var responseMessage = await HttpClient.GetAsync(uri))
|
||||
{
|
||||
if (responseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
IBuffer buffer = null;
|
||||
TimeSpan? maxAge = null;
|
||||
|
||||
if (ImageAvailable(responseMessage.Headers))
|
||||
{
|
||||
buffer = await responseMessage.Content.ReadAsBufferAsync();
|
||||
maxAge = responseMessage.Headers.CacheControl?.MaxAge;
|
||||
}
|
||||
|
||||
response = new HttpBufferResponse(buffer, maxAge);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)responseMessage.StatusCode, responseMessage.ReasonPhrase);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("ImageLoader: {0}: {1}", uri, ex.Message);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private static bool ImageAvailable(HttpResponseHeaderCollection responseHeaders)
|
||||
{
|
||||
return !responseHeaders.TryGetValue("X-VE-Tile-Info", out string tileInfo) || tileInfo != "no-tile";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,9 +139,6 @@
|
|||
<Compile Include="..\Shared\TileImageLoader.cs">
|
||||
<Link>TileImageLoader.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\TileQueue.cs">
|
||||
<Link>TileQueue.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\TileSource.cs">
|
||||
<Link>TileSource.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
|
|
@ -35,36 +36,33 @@ namespace MapControl
|
|||
|
||||
if (cacheBuffer == null || cacheItem.Expiration < DateTime.UtcNow)
|
||||
{
|
||||
var response = await ImageLoader.LoadHttpBufferAsync(uri).ConfigureAwait(false);
|
||||
|
||||
if (response != null) // download succeeded
|
||||
using (var stream = await ImageLoader.LoadImageStreamAsync(uri).ConfigureAwait(false))
|
||||
{
|
||||
if (stream != null) // download succeeded
|
||||
{
|
||||
cacheBuffer = null; // discard cached image
|
||||
|
||||
if (response.Buffer != null) // tile image available
|
||||
if (stream.Length > 0) // tile image available
|
||||
{
|
||||
await LoadTileImageAsync(tile, response.Buffer).ConfigureAwait(false);
|
||||
await Cache.SetAsync(cacheKey, response.Buffer, GetExpiration(response.MaxAge)).ConfigureAwait(false);
|
||||
await SetTileImageAsync(tile, () => ImageLoader.LoadImageAsync(stream)).ConfigureAwait(false);
|
||||
|
||||
await Cache.SetAsync(cacheKey, stream.ToArray().AsBuffer(), GetExpiration(stream.MaxAge)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cacheBuffer != null) // cached image not expired or download failed
|
||||
{
|
||||
await LoadTileImageAsync(tile, cacheBuffer).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task LoadTileImageAsync(Tile tile, IBuffer buffer)
|
||||
{
|
||||
using (var stream = new InMemoryRandomAccessStream())
|
||||
{
|
||||
await stream.WriteAsync(buffer);
|
||||
await stream.WriteAsync(cacheBuffer);
|
||||
stream.Seek(0);
|
||||
|
||||
await SetTileImageAsync(tile, () => ImageLoader.LoadImageAsync(stream)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Task LoadTileImageAsync(Tile tile, TileSource tileSource)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,13 +2,7 @@
|
|||
// © 2019 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
|
@ -67,72 +61,5 @@ namespace MapControl
|
|||
{
|
||||
return Task.Run(() => LoadImage(path));
|
||||
}
|
||||
|
||||
private static async Task<ImageSource> LoadImageAsync(HttpContent content)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
await content.CopyToAsync(stream);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
return LoadImage(stream);
|
||||
}
|
||||
}
|
||||
|
||||
internal class HttpStreamResponse
|
||||
{
|
||||
public readonly MemoryStream Stream;
|
||||
public readonly TimeSpan? MaxAge;
|
||||
|
||||
public HttpStreamResponse(MemoryStream stream, TimeSpan? maxAge)
|
||||
{
|
||||
Stream = stream;
|
||||
MaxAge = maxAge;
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task<HttpStreamResponse> LoadHttpStreamAsync(Uri uri)
|
||||
{
|
||||
HttpStreamResponse response = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var responseMessage = await HttpClient.GetAsync(uri).ConfigureAwait(false))
|
||||
{
|
||||
if (responseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
MemoryStream stream = null;
|
||||
TimeSpan? maxAge = null;
|
||||
|
||||
if (ImageAvailable(responseMessage.Headers))
|
||||
{
|
||||
stream = new MemoryStream();
|
||||
await responseMessage.Content.CopyToAsync(stream).ConfigureAwait(false);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
maxAge = responseMessage.Headers.CacheControl?.MaxAge;
|
||||
}
|
||||
|
||||
response = new HttpStreamResponse(stream, maxAge);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)responseMessage.StatusCode, responseMessage.ReasonPhrase);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("ImageLoader: {0}: {1}", uri, ex.Message);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private static bool ImageAvailable(HttpResponseHeaders responseHeaders)
|
||||
{
|
||||
IEnumerable<string> tileInfo;
|
||||
return !responseHeaders.TryGetValues("X-VE-Tile-Info", out tileInfo) || !tileInfo.Contains("no-tile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,9 +164,6 @@
|
|||
<Compile Include="..\Shared\TileImageLoader.cs">
|
||||
<Link>TileImageLoader.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\TileQueue.cs">
|
||||
<Link>TileQueue.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\TileSource.cs">
|
||||
<Link>TileSource.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
|||
|
|
@ -32,22 +32,23 @@ namespace MapControl
|
|||
{
|
||||
ImageSource image = null;
|
||||
DateTime expiration;
|
||||
var cacheBuffer = GetCachedImage(cacheKey, out expiration);
|
||||
byte[] cacheBuffer;
|
||||
|
||||
GetCachedImage(cacheKey, out cacheBuffer, out expiration);
|
||||
|
||||
if (cacheBuffer == null || expiration < DateTime.UtcNow)
|
||||
{
|
||||
var response = await ImageLoader.LoadHttpStreamAsync(uri).ConfigureAwait(false);
|
||||
|
||||
if (response != null) // download succeeded
|
||||
using (var stream = await ImageLoader.LoadImageStreamAsync(uri).ConfigureAwait(false))
|
||||
{
|
||||
if (stream != null) // download succeeded
|
||||
{
|
||||
cacheBuffer = null; // discard cached image
|
||||
|
||||
if (response.Stream != null) // tile image available
|
||||
{
|
||||
using (var stream = response.Stream)
|
||||
if (stream.Length > 0) // tile image available
|
||||
{
|
||||
image = ImageLoader.LoadImage(stream);
|
||||
SetCachedImage(cacheKey, stream, GetExpiration(response.MaxAge));
|
||||
|
||||
SetCachedImage(cacheKey, stream, GetExpiration(stream.MaxAge));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -79,9 +80,9 @@ namespace MapControl
|
|||
tile.Image.Dispatcher.InvokeAsync(() => tile.SetImage(image));
|
||||
}
|
||||
|
||||
private static byte[] GetCachedImage(string cacheKey, out DateTime expiration)
|
||||
private static void GetCachedImage(string cacheKey, out byte[] buffer, out DateTime expiration)
|
||||
{
|
||||
var buffer = Cache.Get(cacheKey) as byte[];
|
||||
buffer = Cache.Get(cacheKey) as byte[];
|
||||
|
||||
if (buffer != null && buffer.Length >= 16 &&
|
||||
Encoding.ASCII.GetString(buffer, buffer.Length - 16, 8) == "EXPIRES:")
|
||||
|
|
@ -92,8 +93,6 @@ namespace MapControl
|
|||
{
|
||||
expiration = DateTime.MinValue;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static void SetCachedImage(string cacheKey, MemoryStream stream, DateTime expiration)
|
||||
|
|
|
|||
Loading…
Reference in a new issue