Example #1
0
 public void LeaveReadLock()
 {
     Lock.ReleaseReaderLock();
 }
Example #2
0
        // tile consumer thread
        void ProcessLoadTask()
        {
            LoadTask?task = null;
            long     lastTileLoadTimeMs;
            bool     stop = false;

            Thread ct   = Thread.CurrentThread;
            string ctid = "Thread[" + ct.ManagedThreadId + "]";

            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 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();
                        }
                    }
                }
            }

            Monitor.Enter(tileLoadQueue);
            try
            {
                Debug.WriteLine("Quit - " + ct.Name);
                lock (GThreadPool)
                {
                    GThreadPool.Remove(ct);
                }
            }
            finally
            {
                Monitor.Exit(tileLoadQueue);
            }
        }