From 02200eb4d3d2e3ef38c0390212214f08c52b01b3 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 19 Nov 2018 16:12:47 +0300 Subject: [PATCH] Use proper locks for _scene manipulation --- .../Rendering/DeferredRenderer.cs | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index a45ea62cd2..cbf472426f 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -119,8 +119,13 @@ namespace Avalonia.Rendering /// public void Dispose() { - var scene = Interlocked.Exchange(ref _scene, null); - scene?.Dispose(); + lock (_sceneLock) + { + var scene = _scene; + _scene = null; + scene?.Dispose(); + } + Stop(); Layers.Clear(); @@ -135,7 +140,8 @@ namespace Avalonia.Rendering // When unit testing the renderLoop may be null, so update the scene manually. UpdateScene(); } - + //It's safe to access _scene here without a lock since + //it's only changed from UI thread which we are currently on return _scene?.Item.HitTest(p, root, filter) ?? Enumerable.Empty(); } @@ -209,7 +215,10 @@ namespace Avalonia.Rendering bool reRun = false; do { - using (var scene = _scene?.Clone()) + IRef scene; + lock (_sceneLock) + scene = _scene?.Clone(); + using (scene) reRun = Render(scene?.Item, forceComposite, reRun); } while (reRun); } @@ -447,15 +456,23 @@ namespace Avalonia.Rendering } } - var oldScene = Interlocked.Exchange(ref _scene, sceneRef); - oldScene?.Dispose(); + lock (_sceneLock) + { + var oldScene = _scene; + _scene = sceneRef; + oldScene?.Dispose(); + } _dirty.Clear(); } else { - var oldScene = Interlocked.Exchange(ref _scene, null); - oldScene?.Dispose(); + lock (_sceneLock) + { + var oldScene = _scene; + _scene = null; + oldScene?.Dispose(); + } } }