From 376ee843caf68bc986627b75b175b4a57e6fbdd5 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 1 Aug 2020 13:55:15 +0300 Subject: [PATCH] Fixed concurrency issues in RenderLoop --- src/Avalonia.Visuals/Rendering/RenderLoop.cs | 40 ++++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/RenderLoop.cs b/src/Avalonia.Visuals/Rendering/RenderLoop.cs index 789d028a3a..26011e4b92 100644 --- a/src/Avalonia.Visuals/Rendering/RenderLoop.cs +++ b/src/Avalonia.Visuals/Rendering/RenderLoop.cs @@ -18,6 +18,7 @@ namespace Avalonia.Rendering { private readonly IDispatcher _dispatcher; private List _items = new List(); + private List _itemsCopy = new List(); private IRenderTimer _timer; private int _inTick; private int _inUpdate; @@ -63,11 +64,14 @@ namespace Avalonia.Rendering Contract.Requires(i != null); Dispatcher.UIThread.VerifyAccess(); - _items.Add(i); - - if (_items.Count == 1) + lock (_items) { - Timer.Tick += TimerTick; + _items.Add(i); + + if (_items.Count == 1) + { + Timer.Tick += TimerTick; + } } } @@ -76,15 +80,17 @@ namespace Avalonia.Rendering { Contract.Requires(i != null); Dispatcher.UIThread.VerifyAccess(); - - _items.Remove(i); - - if (_items.Count == 0) + lock (_items) { - Timer.Tick -= TimerTick; + _items.Remove(i); + + if (_items.Count == 0) + { + Timer.Tick -= TimerTick; + } } } - + private void TimerTick(TimeSpan time) { if (Interlocked.CompareExchange(ref _inTick, 1, 0) == 0) @@ -129,10 +135,20 @@ namespace Avalonia.Rendering }, DispatcherPriority.Render); } - for(int i = 0; i < _items.Count; i++) + lock (_items) { - _items[i].Render(); + _itemsCopy.Clear(); + foreach (var i in _items) + _itemsCopy.Add(i); } + + for (int i = 0; i < _itemsCopy.Count; i++) + { + _itemsCopy[i].Render(); + } + + _itemsCopy.Clear(); + } catch (Exception ex) {