// tile consumer thread void ProcessLoadTask() { LoadTask? task = null; long lastTileLoadTimeMs; bool stop = false; #if !PocketPC Thread ct = Thread.CurrentThread; string ctid = "Thread[" + ct.ManagedThreadId + "]"; #else int ctid = 0; #endif while(!stop && IsStarted) { task = null; Monitor.Enter(tileLoadQueue); try { while(tileLoadQueue.Count == 0) { Debug.WriteLine(ctid + " - Wait " + loadWaitCount + " - " + DateTime.Now.TimeOfDay); if(++loadWaitCount >= GThreadPoolSize) { loadWaitCount = 0; #region -- last thread takes action -- { LastTileLoadEnd = DateTime.Now; lastTileLoadTimeMs = (long)(LastTileLoadEnd - LastTileLoadStart).TotalMilliseconds; } #region -- clear stuff-- if(IsStarted) { GMaps.Instance.MemoryCache.RemoveOverload(); tileDrawingListLock.AcquireReaderLock(); try { Matrix.ClearLevelAndPointsNotIn(Zoom, tileDrawingList); } finally { tileDrawingListLock.ReleaseReaderLock(); } } #endregion UpdateGroundResolution(); #if UseGC GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); #endif Debug.WriteLine(ctid + " - OnTileLoadComplete: " + lastTileLoadTimeMs + "ms, MemoryCacheSize: " + GMaps.Instance.MemoryCache.Size + "MB"); if(OnTileLoadComplete != null) { OnTileLoadComplete(lastTileLoadTimeMs); } #endregion } if(!IsStarted || false == Monitor.Wait(tileLoadQueue, WaitForTileLoadThreadTimeout, false) || !IsStarted) { stop = true; break; } } if(IsStarted && !stop || tileLoadQueue.Count > 0) { task = tileLoadQueue.Pop(); } } finally { Monitor.Exit(tileLoadQueue); } if(task.HasValue && IsStarted) { try { #region -- execute -- var m = Matrix.GetTileWithReadLock(task.Value.Zoom, task.Value.Pos); if(!m.NotEmpty) { Debug.WriteLine(ctid + " - try load: " + task); Tile t = new Tile(task.Value.Zoom, task.Value.Pos); foreach(var tl in provider.Overlays) { int retry = 0; do { PureImage img = null; Exception ex = null; if (task.Value.Zoom >= provider.MinZoom && (!provider.MaxZoom.HasValue || task.Value.Zoom <= provider.MaxZoom)) { if(skipOverZoom == 0 || task.Value.Zoom <= skipOverZoom) { // tile number inversion(BottomLeft -> TopLeft) if(tl.InvertedAxisY) { img = GMaps.Instance.GetImageFrom(tl, new GPoint(task.Value.Pos.X, maxOfTiles.Height - task.Value.Pos.Y), task.Value.Zoom, out ex); } else // ok { img = GMaps.Instance.GetImageFrom(tl, task.Value.Pos, task.Value.Zoom, out ex); } } } if(img != null && ex == null) { if(okZoom < task.Value.Zoom) { okZoom = task.Value.Zoom; skipOverZoom = 0; Debug.WriteLine("skipOverZoom disabled, okZoom: " + okZoom); } } else if(ex != null) { if ((skipOverZoom != okZoom) && (task.Value.Zoom > okZoom)) { if(ex.Message.Contains("(404) Not Found")) { skipOverZoom = okZoom; Debug.WriteLine("skipOverZoom enabled: " + skipOverZoom); } } } // check for parent tiles if not found if(img == null && okZoom > 0 && fillEmptyTiles && Provider.Projection is MercatorProjection) { int zoomOffset = task.Value.Zoom > okZoom ? task.Value.Zoom - okZoom : 1; long Ix = 0; GPoint parentTile = GPoint.Empty; while(img == null && zoomOffset < task.Value.Zoom) { Ix = (long)Math.Pow(2, zoomOffset); parentTile = new GMap.NET.GPoint((task.Value.Pos.X / Ix), (task.Value.Pos.Y / Ix)); img = GMaps.Instance.GetImageFrom(tl, parentTile, task.Value.Zoom - zoomOffset++, out ex); } if(img != null) { // offsets in quadrant long Xoff = Math.Abs(task.Value.Pos.X - (parentTile.X * Ix)); long Yoff = Math.Abs(task.Value.Pos.Y - (parentTile.Y * Ix)); img.IsParent = true; img.Ix = Ix; img.Xoff = Xoff; img.Yoff = Yoff; // wpf //var geometry = new RectangleGeometry(new Rect(Core.tileRect.X + 0.6, Core.tileRect.Y + 0.6, Core.tileRect.Width + 0.6, Core.tileRect.Height + 0.6)); //var parentImgRect = new Rect(Core.tileRect.X - Core.tileRect.Width * Xoff + 0.6, Core.tileRect.Y - Core.tileRect.Height * Yoff + 0.6, Core.tileRect.Width * Ix + 0.6, Core.tileRect.Height * Ix + 0.6); // gdi+ //System.Drawing.Rectangle dst = new System.Drawing.Rectangle((int)Core.tileRect.X, (int)Core.tileRect.Y, (int)Core.tileRect.Width, (int)Core.tileRect.Height); //System.Drawing.RectangleF srcRect = new System.Drawing.RectangleF((float)(Xoff * (img.Img.Width / Ix)), (float)(Yoff * (img.Img.Height / Ix)), (img.Img.Width / Ix), (img.Img.Height / Ix)); } } if(img != null) { Debug.WriteLine(ctid + " - tile loaded: " + img.Data.Length / 1024 + "KB, " + task); { t.AddOverlay(img); } break; } else { if(ex != null) { lock(FailedLoads) { if(!FailedLoads.ContainsKey(task.Value)) { FailedLoads.Add(task.Value, ex); if(OnEmptyTileError != null) { if(!RaiseEmptyTileError) { RaiseEmptyTileError = true; OnEmptyTileError(task.Value.Zoom, task.Value.Pos); } } } } } if(RetryLoadTile > 0) { Debug.WriteLine(ctid + " - ProcessLoadTask: " + task + " -> empty tile, retry " + retry); { Thread.Sleep(1111); } } } } while(++retry < RetryLoadTile); } if(t.HasAnyOverlays && IsStarted) { Matrix.SetTile(t); } else { t.Dispose(); } } #endregion } catch(Exception ex) { Debug.WriteLine(ctid + " - ProcessLoadTask: " + ex.ToString()); } finally { if(Refresh != null) { Refresh.Set(); } } } } #if !PocketPC Monitor.Enter(tileLoadQueue); try { Debug.WriteLine("Quit - " + ct.Name); lock(GThreadPool) { GThreadPool.Remove(ct); } } finally { Monitor.Exit(tileLoadQueue); } #endif }
void ProcessLoadTask() { bool invalidate = false; LoadTask? task = null; long lastTileLoadTimeMs; bool stop = false; Thread ct = Thread.CurrentThread; string ctid = "Thread[" + ct.ManagedThreadId + "]"; while (!stop) { invalidate = false; task = null; lock (tileLoadQueue) { while (tileLoadQueue.Count == 0) { Debug.WriteLine(ctid + " - Wait " + loadWaitCount + " - " + DateTime.Now.TimeOfDay); if (++loadWaitCount >= GThreadPoolSize) { loadWaitCount = 0; lock (LastInvalidationLock) { LastInvalidation = DateTime.Now; } if (OnNeedInvalidation != null) { OnNeedInvalidation(); } lock (LastTileLoadStartEndLock) { LastTileLoadEnd = DateTime.Now; lastTileLoadTimeMs = (long)(LastTileLoadEnd - LastTileLoadStart).TotalMilliseconds; } #region -- clear stuff-- { GMaps.Instance.kiberCacheLock.AcquireWriterLock(); try { GMaps.Instance.TilesInMemory.RemoveMemoryOverload(); } finally { GMaps.Instance.kiberCacheLock.ReleaseWriterLock(); } tileDrawingListLock.AcquireReaderLock(); try { Matrix.ClearLevelAndPointsNotIn(Zoom, tileDrawingList); } finally { tileDrawingListLock.ReleaseReaderLock(); } } #endregion UpdateGroundResolution(); Debug.WriteLine(ctid + " - OnTileLoadComplete: " + lastTileLoadTimeMs + "ms, MemoryCacheSize: " + GMaps.Instance.MemoryCacheSize + "MB"); if (OnTileLoadComplete != null) { OnTileLoadComplete(lastTileLoadTimeMs); } } if (false == Monitor.Wait(tileLoadQueue, WaitForTileLoadThreadTimeout, false)) { stop = true; break; } } if (!stop || tileLoadQueue.Count > 0) { task = tileLoadQueue.Dequeue(); } } if (task.HasValue) { try { #region -- execute -- var m = Matrix.GetTileWithReadLock(task.Value.Zoom, task.Value.Pos); if (m == null || m.Overlays.Count == 0) { Debug.WriteLine(ctid + " - Fill empty TileMatrix: " + task); Tile t = new Tile(task.Value.Zoom, task.Value.Pos); var layers = GMaps.Instance.GetAllLayersOfType(MapType); foreach (MapType tl in layers) { int retry = 0; do { PureImage img; Exception ex; // tile number inversion(BottomLeft -> TopLeft) for pergo maps img = GMaps.Instance.GetImageFrom(tl, task.Value.Pos, task.Value.Zoom, out ex); if (img != null) { lock (t.Overlays) { t.Overlays.Add(img); } break; } else { if (ex != null) { lock (FailedLoads) { if (!FailedLoads.ContainsKey(task.Value)) { FailedLoads.Add(task.Value, ex); if (OnEmptyTileError != null) { if (!RaiseEmptyTileError) { RaiseEmptyTileError = true; OnEmptyTileError(task.Value.Zoom, task.Value.Pos); } } } } } if (RetryLoadTile > 0) { Debug.WriteLine(ctid + " - ProcessLoadTask: " + task + " -> empty tile, retry " + retry); { Thread.Sleep(1111); } } } } while (++retry < RetryLoadTile); } if (t.Overlays.Count > 0) { Matrix.SetTile(t); } else { t.Clear(); t = null; } layers = null; } #endregion } catch (Exception ex) { Debug.WriteLine(ctid + " - ProcessLoadTask: " + ex.ToString()); } finally { lock (LastInvalidationLock) { invalidate = ((DateTime.Now - LastInvalidation).TotalMilliseconds > 111); if (invalidate) { LastInvalidation = DateTime.Now; } } if (invalidate) { if (OnNeedInvalidation != null) { OnNeedInvalidation(); } } } } } lock (tileLoadQueue) { Debug.WriteLine("Quit - " + ct.Name); GThreadPool.Remove(ct); } }
public void SetTile(Tile t) { Lock.AcquireWriterLock(); try { if(t.Zoom < Levels.Count) { Levels[t.Zoom][t.Pos] = t; } } finally { Lock.ReleaseWriterLock(); } }
static void ProcessLoadTask(LoadTask task, string ctid) { try { #region -- execute -- var m = task.Core.Matrix.GetTileWithReadLock(task.Zoom, task.Pos); if (!m.NotEmpty) { Debug.WriteLine(ctid + " - try load: " + task); Tile t = new Tile(task.Zoom, task.Pos); foreach (var tl in task.Core.provider.Overlays) { int retry = 0; do { PureImage img = null; Exception ex = null; if (task.Zoom >= task.Core.provider.MinZoom && (!task.Core.provider.MaxZoom.HasValue || task.Zoom <= task.Core.provider.MaxZoom)) { if (task.Core.skipOverZoom == 0 || task.Zoom <= task.Core.skipOverZoom) { // tile number inversion(BottomLeft -> TopLeft) if (tl.InvertedAxisY) { img = GMaps.Instance.GetImageFrom(tl, new GPoint(task.Pos.X, task.Core.maxOfTiles.Height - task.Pos.Y), task.Zoom, out ex); } else // ok { img = GMaps.Instance.GetImageFrom(tl, task.Pos, task.Zoom, out ex); } } } if (img != null && ex == null) { if (task.Core.okZoom < task.Zoom) { task.Core.okZoom = task.Zoom; task.Core.skipOverZoom = 0; Debug.WriteLine("skipOverZoom disabled, okZoom: " + task.Core.okZoom); } } else if (ex != null) { if ((task.Core.skipOverZoom != task.Core.okZoom) && (task.Zoom > task.Core.okZoom)) { if (ex.Message.Contains("(404) Not Found")) { task.Core.skipOverZoom = task.Core.okZoom; Debug.WriteLine("skipOverZoom enabled: " + task.Core.skipOverZoom); } } } // check for parent tiles if not found if (img == null && task.Core.okZoom > 0 && task.Core.fillEmptyTiles && task.Core.Provider.Projection is MercatorProjection) { int zoomOffset = task.Zoom > task.Core.okZoom ? task.Zoom - task.Core.okZoom : 1; long Ix = 0; GPoint parentTile = GPoint.Empty; while (img == null && zoomOffset < task.Zoom) { Ix = (long)Math.Pow(2, zoomOffset); parentTile = new GMap.NET.GPoint((task.Pos.X / Ix), (task.Pos.Y / Ix)); img = GMaps.Instance.GetImageFrom(tl, parentTile, task.Zoom - zoomOffset++, out ex); } if (img != null) { // offsets in quadrant long Xoff = Math.Abs(task.Pos.X - (parentTile.X * Ix)); long Yoff = Math.Abs(task.Pos.Y - (parentTile.Y * Ix)); img.IsParent = true; img.Ix = Ix; img.Xoff = Xoff; img.Yoff = Yoff; // wpf //var geometry = new RectangleGeometry(new Rect(Core.tileRect.X + 0.6, Core.tileRect.Y + 0.6, Core.tileRect.Width + 0.6, Core.tileRect.Height + 0.6)); //var parentImgRect = new Rect(Core.tileRect.X - Core.tileRect.Width * Xoff + 0.6, Core.tileRect.Y - Core.tileRect.Height * Yoff + 0.6, Core.tileRect.Width * Ix + 0.6, Core.tileRect.Height * Ix + 0.6); // gdi+ //System.Drawing.Rectangle dst = new System.Drawing.Rectangle((int)Core.tileRect.X, (int)Core.tileRect.Y, (int)Core.tileRect.Width, (int)Core.tileRect.Height); //System.Drawing.RectangleF srcRect = new System.Drawing.RectangleF((float)(Xoff * (img.Img.Width / Ix)), (float)(Yoff * (img.Img.Height / Ix)), (img.Img.Width / Ix), (img.Img.Height / Ix)); } } if (img != null) { Debug.WriteLine(ctid + " - tile loaded: " + img.Data.Length / 1024 + "KB, " + task); { t.AddOverlay(img); } break; } else { if (ex != null) { lock (task.Core.FailedLoads) { if (!task.Core.FailedLoads.ContainsKey(task)) { task.Core.FailedLoads.Add(task, ex); if (task.Core.OnEmptyTileError != null) { if (!task.Core.RaiseEmptyTileError) { task.Core.RaiseEmptyTileError = true; task.Core.OnEmptyTileError(task.Zoom, task.Pos); } } } } } if (task.Core.RetryLoadTile > 0) { Debug.WriteLine(ctid + " - ProcessLoadTask: " + task + " -> empty tile, retry " + retry); { Thread.Sleep(1111); } } } } while (++retry < task.Core.RetryLoadTile); } if (t.HasAnyOverlays && task.Core.IsStarted) { task.Core.Matrix.SetTile(t); } else { t.Dispose(); } } #endregion } catch (Exception ex) { Debug.WriteLine(ctid + " - ProcessLoadTask: " + ex.ToString()); } finally { if (task.Core.Refresh != null) { task.Core.Refresh.Set(); } } }