Skip to content

Commit fe64e03

Browse files
committed
Make Window.Invalidate() non-blocking with Monitor.TryEnter
Replace lock(_lock) with Monitor.TryEnter to prevent UI freezes when background threads call Invalidate() while the render thread holds the lock. If the lock is contended, the targeted node invalidation is skipped but _invalidated and IsDirty flags are still set, so the render loop does a full layout rebuild on the next frame.
1 parent 220cb57 commit fe64e03

1 file changed

Lines changed: 25 additions & 15 deletions

File tree

SharpConsoleUI/Window.cs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,28 +1552,38 @@ public void Invalidate(bool redrawAll, IWindowControl? callerControl = null)
15521552
{
15531553
_invalidated = true;
15541554

1555-
lock (_lock)
1555+
// Use TryEnter to avoid blocking when the render thread holds the lock.
1556+
// If we can't acquire it, _invalidated + IsDirty are still set, so the
1557+
// render loop will do a full layout rebuild on the next frame.
1558+
if (Monitor.TryEnter(_lock))
15561559
{
1557-
if (redrawAll)
1558-
{
1559-
// Invalidate measurements without rebuilding the tree
1560-
// This preserves runtime state like splitter positions
1561-
_renderer?.InvalidateDOMLayout();
1562-
}
1563-
else if (callerControl != null)
1560+
try
15641561
{
1565-
// Specific control invalidation
1566-
var node = _renderer?.GetLayoutNode(callerControl);
1567-
if (node != null)
1562+
if (redrawAll)
15681563
{
1569-
node.InvalidateMeasure();
1564+
// Invalidate measurements without rebuilding the tree
1565+
// This preserves runtime state like splitter positions
1566+
_renderer?.InvalidateDOMLayout();
15701567
}
1571-
else
1568+
else if (callerControl != null)
15721569
{
1573-
// Fallback: invalidate entire tree
1574-
_renderer?.InvalidateDOMLayout();
1570+
// Specific control invalidation
1571+
var node = _renderer?.GetLayoutNode(callerControl);
1572+
if (node != null)
1573+
{
1574+
node.InvalidateMeasure();
1575+
}
1576+
else
1577+
{
1578+
// Fallback: invalidate entire tree
1579+
_renderer?.InvalidateDOMLayout();
1580+
}
15751581
}
15761582
}
1583+
finally
1584+
{
1585+
Monitor.Exit(_lock);
1586+
}
15771587
}
15781588

15791589
IsDirty = true;

0 commit comments

Comments
 (0)