From bd811aac7d847e93ea8839fc83c7fb2dab7c9018 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sat, 28 Dec 2019 21:37:05 +0200 Subject: [PATCH] Fixed deadlock caused by errors displayed by texture loading --- Source/Core/Controls/DebugConsole.cs | 46 +++++------ Source/Core/Windows/MainForm.cs | 111 ++++++++++++++++----------- 2 files changed, 88 insertions(+), 69 deletions(-) diff --git a/Source/Core/Controls/DebugConsole.cs b/Source/Core/Controls/DebugConsole.cs index 69b38639..da168c60 100755 --- a/Source/Core/Controls/DebugConsole.cs +++ b/Source/Core/Controls/DebugConsole.cs @@ -46,11 +46,11 @@ namespace CodeImp.DoomBuilder private static string storedtext = string.Empty; private static DebugConsole me; - #endregion + #endregion - #region ================== Properties + #region ================== Properties - public bool AlwaysOnTop { get { return alwaysontop.Checked; } } + public bool AlwaysOnTop { get { return alwaysontop.Checked; } } public static int Counter { get { return counter; } } #endregion @@ -106,32 +106,28 @@ namespace CodeImp.DoomBuilder public static void Write(DebugMessageType type, string text) { Write(type, text, true); } public static void Write(DebugMessageType type, string text, bool append) { - if(me != null && me.InvokeRequired) - { - me.Invoke(new Action(Write), new object[] { type, text, append }); - } - else - { - if(messages.Count + 1 > MAX_MESSAGES) lock (messages) { messages.RemoveAt(0); } - messages.Add(new KeyValuePair(type, text)); - if(me != null && (me.filters & type) == type) - { - me.AddMessage(type, text, true, append); - } - } + if (General.MainWindow == null) + return; + General.MainWindow.RunOnUIThread(() => + { + if (messages.Count + 1 > MAX_MESSAGES) lock (messages) { messages.RemoveAt(0); } + messages.Add(new KeyValuePair(type, text)); + if (me != null && (me.filters & type) == type) + { + me.AddMessage(type, text, true, append); + } + }); } public static void Clear() { - if(me != null && me.InvokeRequired) - { - me.Invoke(new Action(Clear)); - } - else - { - if(me != null) me.console.Clear(); - messages.Clear(); - } + if (General.MainWindow == null) + return; + General.MainWindow.RunOnUIThread(() => + { + if (me != null) me.console.Clear(); + messages.Clear(); + }); } public static void StartTimer() diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs index 8d1a855d..98523b42 100755 --- a/Source/Core/Windows/MainForm.cs +++ b/Source/Core/Windows/MainForm.cs @@ -282,6 +282,11 @@ namespace CodeImp.DoomBuilder.Windows //mxd. Hints hintsPanel = new HintsPanel(); hintsDocker = new Docker("hints", "Help", hintsPanel); + + // [ZZ] + InvokeTimer.Tick += new EventHandler(InvokeHandler); + InvokeTimer.Interval = 10; + InvokeTimer.Start(); } #endregion @@ -4112,12 +4117,37 @@ namespace CodeImp.DoomBuilder.Windows #region ================== Threadsafe updates + Timer InvokeTimer = new Timer(); + List InvokeActions = new List(); + + // this is actually InvokeTimer.Tick handler + void InvokeHandler(object sender, EventArgs e) + { + InvokeTimer.Stop(); + + List actions = null; + lock (InvokeActions) + { + if (InvokeActions.Count > 0) + { + actions = new List(); + actions.AddRange(InvokeActions); + } + } + + if (actions == null) + return; + + foreach (System.Action action in actions) + action(); + + InvokeTimer.Start(); + } + public void RunOnUIThread(System.Action action) { - if (InvokeRequired) - Invoke(action); - else - action(); + if (!InvokeRequired) action(); + else lock (InvokeActions) InvokeActions.Add(action); } public void UpdateStatus() @@ -4198,28 +4228,24 @@ namespace CodeImp.DoomBuilder.Windows private delegate void SetWarningsCountCallback(int count, bool blink); internal void SetWarningsCount(int count, bool blink) { - if(this.InvokeRequired) - { - SetWarningsCountCallback d = SetWarningsCount; - this.Invoke(d, new object[] { count, blink }); - return; - } + RunOnUIThread(() => + { + // Update icon, start annoying blinking if necessary + if (count > 0) + { + if (blink && !blinkTimer.Enabled) blinkTimer.Start(); + warnsLabel.Image = Resources.Warning; + } + else + { + blinkTimer.Stop(); + warnsLabel.Image = Resources.WarningOff; + warnsLabel.BackColor = SystemColors.Control; + } - // Update icon, start annoying blinking if necessary - if(count > 0) - { - if(blink && !blinkTimer.Enabled) blinkTimer.Start(); - warnsLabel.Image = Resources.Warning; - } - else - { - blinkTimer.Stop(); - warnsLabel.Image = Resources.WarningOff; - warnsLabel.BackColor = SystemColors.Control; - } - - // Update errors count - warnsLabel.Text = count.ToString(); + // Update errors count + warnsLabel.Text = count.ToString(); + }); } //mxd. Bliks warnings indicator @@ -4240,7 +4266,10 @@ namespace CodeImp.DoomBuilder.Windows if(!blinkTimer.Enabled) return; try { - this.Invoke(new CallBlink(Blink)); + RunOnUIThread(() => + { + Blink(); + }); } catch(ObjectDisposedException) { } //la-la-la. We don't care. } @@ -4465,24 +4494,18 @@ namespace CodeImp.DoomBuilder.Windows #region ================== Updater (mxd) private delegate void UpdateAvailableCallback(int remoterev, string changelog); - internal void UpdateAvailable(int remoterev, string changelog) - { - if(this.InvokeRequired) - { - UpdateAvailableCallback d = UpdateAvailable; - this.Invoke(d, new object[] { remoterev, changelog }); - } - else - { - // Show the window - UpdateForm form = new UpdateForm(remoterev, changelog); - form.FormClosing += delegate - { - // Update ignored revision number - General.Settings.IgnoredRemoteRevision = (form.IgnoreThisUpdate ? remoterev : 0); - }; - form.Show(this); - } + internal void UpdateAvailable(int remoterev, string changelog) + { + RunOnUIThread(() => { + // Show the window + UpdateForm form = new UpdateForm(remoterev, changelog); + form.FormClosing += delegate + { + // Update ignored revision number + General.Settings.IgnoredRemoteRevision = (form.IgnoreThisUpdate ? remoterev : 0); + }; + form.Show(this); + }); } #endregion