void ProcessLoadTask() { bool invalidate = false; 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) { 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(); #if UseGC GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); #endif Debug.WriteLine(ctid + " - OnTileLoadComplete: " + lastTileLoadTimeMs + "ms, MemoryCacheSize: " + GMaps.Instance.MemoryCacheSize + "MB"); if (OnTileLoadComplete != null) { OnTileLoadComplete(lastTileLoadTimeMs); } } #if !PocketPC if (false == Monitor.Wait(tileLoadQueue, WaitForTileLoadThreadTimeout, false)) { stop = true; break; } #else wait.Wait(); #endif } 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 if (tl == MapType.PergoTurkeyMap) { img = GMaps.Instance.GetImageFrom(tl, new Point(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) { 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(); } } #if DEBUG //else //{ // lock(LastInvalidationLock) // { // Debug.WriteLine(ctid + " - SkipInvalidation, Delta: " + (DateTime.Now - LastInvalidation).TotalMilliseconds + "ms"); // } //} #endif } } } #if !PocketPC lock (tileLoadQueue) { Debug.WriteLine("Quit - " + ct.Name); GThreadPool.Remove(ct); } #endif }
/// <summary> /// updates map bounds /// </summary> void UpdateBounds() { if (MapType == NET.MapType.None) { return; } lock (tileLoadQueue) { tileDrawingListLock.AcquireWriterLock(); try { #region -- find tiles around -- tileDrawingList.Clear(); for (int i = -sizeOfMapArea.Width; i <= sizeOfMapArea.Width; i++) { for (int j = -sizeOfMapArea.Height; j <= sizeOfMapArea.Height; j++) { Point p = centerTileXYLocation; p.X += i; p.Y += j; #if ContinuesMap // ---------------------------- if (p.X < minOfTiles.Width) { p.X += (maxOfTiles.Width + 1); } if (p.X > maxOfTiles.Width) { p.X -= (maxOfTiles.Width + 1); } // ---------------------------- #endif if (p.X >= minOfTiles.Width && p.Y >= minOfTiles.Height && p.X <= maxOfTiles.Width && p.Y <= maxOfTiles.Height) { if (!tileDrawingList.Contains(p)) { tileDrawingList.Add(p); } } } } if (GMaps.Instance.ShuffleTilesOnLoad) { Stuff.Shuffle <Point>(tileDrawingList); } #endregion foreach (Point p in tileDrawingList) { LoadTask task = new LoadTask(p, Zoom); { if (!tileLoadQueue.Contains(task)) { tileLoadQueue.Enqueue(task); } } } } finally { tileDrawingListLock.ReleaseWriterLock(); } #region -- starts loader threads if needed -- #if !PocketPC while (GThreadPool.Count < GThreadPoolSize) #else while (GThreadPool.Count < GThreadPoolSize) #endif { Thread t = new Thread(new ThreadStart(ProcessLoadTask)); { t.Name = "GMap.NET TileLoader: " + GThreadPool.Count; t.IsBackground = true; t.Priority = ThreadPriority.BelowNormal; } GThreadPool.Add(t); Debug.WriteLine("add " + t.Name + " to GThreadPool"); t.Start(); } #endregion lock (LastTileLoadStartEndLock) { LastTileLoadStart = DateTime.Now; Debug.WriteLine("OnTileLoadStart - at zoom " + Zoom + ", time: " + LastTileLoadStart.TimeOfDay); } loadWaitCount = 0; #if !PocketPC Monitor.PulseAll(tileLoadQueue); #else wait.PulseAll(); #endif } if (OnTileLoadStart != null) { OnTileLoadStart(); } }