# HG changeset patch # User Ivo Smits # Date 1392672952 -3600 # Node ID 0d389692be32a2af1f8117992bf4b144ecc78206 # Parent 4714531734b364e24928eaee22c94313acff2e7f FBGUI: Separated locking in renderer so Invalidate does not block while Painting in timer callback diff -r 4714531734b3 -r 0d389692be32 FBGUI/FBGUI.cs --- a/FBGUI/FBGUI.cs Sun Feb 16 15:05:31 2014 +0100 +++ b/FBGUI/FBGUI.cs Mon Feb 17 22:35:52 2014 +0100 @@ -630,6 +630,7 @@ public IFramebuffer Framebuffer { get; private set; } private Bitmap Frontbuffer = null; protected Object RenderLock = new object(); + private Object StatusLock = new object(); public event EventHandler Painted; protected Size size = Size.Empty; private ThreadingTimer PaintTimer = null; @@ -638,29 +639,28 @@ public Boolean SuspendDrawing { get { return suspenddrawing; } set { + lock (StatusLock) suspenddrawing = value; + if (value) return; lock (RenderLock) { - suspenddrawing = value; - if (!value) { - Refresh(DirtyRectangle); - DirtyRectangle = Rectangle.Empty; - } + Refresh(DirtyRectangle); + DirtyRectangle = Rectangle.Empty; } } } public int RedrawDelay { get { return PaintDelay; } set { - lock (RenderLock) { + lock (StatusLock) { if (value < 0) throw new ArgumentOutOfRangeException("value"); PaintDelay = value; if (PaintDelay == 0) { if (PaintTimer != null) PaintTimer.Dispose(); PaintTimer = null; - if (PaintScheduled) PaintTimerCallback(null); } else { PaintTimer = new ThreadingTimer(PaintTimerCallback); } } + if (PaintScheduled) PaintTimerCallback(null); } } private Boolean suspenddrawing = false; @@ -709,7 +709,8 @@ } public override void Invalidate(Rectangle rect) { if (rect.Width == 0 || rect.Height == 0) return; - lock (RenderLock) { + Boolean drawDirect = false; + lock (StatusLock) { if (SuspendDrawing || PaintTimer != null) { DirtyRectangle = DirtyRectangle.IsEmpty ? rect : Rectangle.Union(DirtyRectangle, rect); if (!SuspendDrawing && !PaintScheduled) { @@ -717,17 +718,20 @@ PaintTimer.Change(PaintDelay, Timeout.Infinite); } } else { - Refresh(rect); + drawDirect = true; } } + if (drawDirect) Refresh(rect); } private void PaintTimerCallback(Object state) { try { - lock (RenderLock) { + Rectangle rect; + lock (StatusLock) { PaintScheduled = false; - Refresh(DirtyRectangle); + rect = DirtyRectangle; DirtyRectangle = Rectangle.Empty; } + Refresh(rect); } catch (Exception ex) { Debug.WriteLine(ex); Console.Error.WriteLine(ex); @@ -776,7 +780,7 @@ return true; } public virtual void Dispose() { - lock (RenderLock) { + lock (StatusLock) { if (PaintTimer != null) PaintTimer.Dispose(); PaintTimer = null; }