diff --git a/Intersect.Client.Core/Interface/Game/Admin/BanMuteBox.cs b/Intersect.Client.Core/Interface/Game/Admin/BanMuteBox.cs index c2b10bc919..eb87b7c09e 100644 --- a/Intersect.Client.Core/Interface/Game/Admin/BanMuteBox.cs +++ b/Intersect.Client.Core/Interface/Game/Admin/BanMuteBox.cs @@ -103,14 +103,14 @@ public BanMuteBox(string title, string prompt, EventHandler okayHandler) : base( buttonOkay.Clicked += (s, e) => { okayHandler?.Invoke(this, EventArgs.Empty); - Dispose(); + DelayedDelete(); }; var buttonCancel = new Button(this, "ButtonCancel") { Text = Strings.BanMute.Cancel, }; - buttonCancel.Clicked += (s, e) => Dispose(); + buttonCancel.Clicked += (s, e) => DelayedDelete(); LoadJsonUi(UI.InGame, Graphics.Renderer?.GetResolutionString(), true); diff --git a/Intersect.Client.Framework/Gwen/Control/Canvas.cs b/Intersect.Client.Framework/Gwen/Control/Canvas.cs index 93ebdb559c..8f22038641 100644 --- a/Intersect.Client.Framework/Gwen/Control/Canvas.cs +++ b/Intersect.Client.Framework/Gwen/Control/Canvas.cs @@ -262,21 +262,42 @@ public void AddDelayedDelete(Base control) private void ProcessDelayedDeletes() { + List controlsToDispose; + lock (_disposeQueue) { - foreach (var control in _disposeQueue) + if (_disposeQueue.Count == 0) { + return; + } + + controlsToDispose = new List(_disposeQueue); + _disposeQueue.Clear(); + #if DEBUG - if (control is Base node) - { - _delayedDeleteStackTraces.Remove(node); - } + // Remove all the stuff from debug tracking in one go + _delayedDeleteStackTraces.Clear(); #endif + } + // Dispose outside the lock + foreach (var control in controlsToDispose) + { + try + { control.Dispose(); } - - _disposeQueue.Clear(); + catch (ObjectDisposedException) + { + // Already disposed, ignore + } + catch (Exception ex) + { + ApplicationContext.Context.Value?.Logger.LogError( + ex, + "Error disposing control during ProcessDelayedDeletes" + ); + } } }