/// <summary>Service routine to paint the backing store bitmap for the map underlay.</summary> protected virtual Bitmap PaintBuffer(Rectangle clipBounds) { if (DataContext.Model == null) { return(null); } Bitmap bitmap = null, temp = null; try { temp = ClientSize.AllocateBitmap(); using (var graphics = Graphics.FromImage(temp)) { graphics.Clip = new Region(clipBounds); graphics.Contain(PaintBuffer); } bitmap = temp; temp = null; } finally { if (temp != null) { temp.Dispose(); } } return(bitmap); }
/// <inheritdoc/> protected override async void OnPaint(PaintEventArgs e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } if (DesignMode) { e.Graphics.FillRectangle(Brushes.Gray, ClientRectangle); return; } if (IsMapDirty) { OnResize(EventArgs.Empty); IsMapDirty = false; } // TODO - Fix thread timing error work-around of catching and discarding InvalidOperationException. if (_mapBuffer != null) { try { base.OnPaint(e); } catch (InvalidOperationException) { _count++; } } var status = Interlocked.CompareExchange(ref _cacheStatus, _IS_PAINTING, _NEEDS_PAINTING); if (status == _NEEDS_PAINTING) { try { if (_backBuffer != null) { _backBuffer.Dispose(); } _backBuffer = Interlocked.Exchange(ref _mapBuffer, await PaintBufferAsync(ClientRectangle)); if (_backBuffer != null) { _backBuffer.Dispose(); } _backBuffer = ClientSize.AllocateBitmap(); } catch (InvalidOperationException) { if (_backBuffer == null) { _backBuffer = ClientSize.AllocateBitmap(); } Interlocked.CompareExchange(ref _cacheStatus, _NEEDS_PAINTING, _IS_PAINTING); Thread.Sleep(250); } finally { Interlocked.CompareExchange(ref _cacheStatus, _IS_READY, _IS_PAINTING); } Refresh(); } IsUnitsDirty = false; }