Browse Source

Use proper locks for _scene manipulation

pull/2117/head
Nikita Tsukanov 8 years ago
parent
commit
02200eb4d3
  1. 33
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

33
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -119,8 +119,13 @@ namespace Avalonia.Rendering
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
var scene = Interlocked.Exchange(ref _scene, null); lock (_sceneLock)
scene?.Dispose(); {
var scene = _scene;
_scene = null;
scene?.Dispose();
}
Stop(); Stop();
Layers.Clear(); Layers.Clear();
@ -135,7 +140,8 @@ namespace Avalonia.Rendering
// When unit testing the renderLoop may be null, so update the scene manually. // When unit testing the renderLoop may be null, so update the scene manually.
UpdateScene(); 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<IVisual>(); return _scene?.Item.HitTest(p, root, filter) ?? Enumerable.Empty<IVisual>();
} }
@ -209,7 +215,10 @@ namespace Avalonia.Rendering
bool reRun = false; bool reRun = false;
do do
{ {
using (var scene = _scene?.Clone()) IRef<Scene> scene;
lock (_sceneLock)
scene = _scene?.Clone();
using (scene)
reRun = Render(scene?.Item, forceComposite, reRun); reRun = Render(scene?.Item, forceComposite, reRun);
} while (reRun); } while (reRun);
} }
@ -447,15 +456,23 @@ namespace Avalonia.Rendering
} }
} }
var oldScene = Interlocked.Exchange(ref _scene, sceneRef); lock (_sceneLock)
oldScene?.Dispose(); {
var oldScene = _scene;
_scene = sceneRef;
oldScene?.Dispose();
}
_dirty.Clear(); _dirty.Clear();
} }
else else
{ {
var oldScene = Interlocked.Exchange(ref _scene, null); lock (_sceneLock)
oldScene?.Dispose(); {
var oldScene = _scene;
_scene = null;
oldScene?.Dispose();
}
} }
} }

Loading…
Cancel
Save