Fixed deadlock caused by errors displayed by texture loading

This commit is contained in:
ZZYZX 2019-12-28 21:37:05 +02:00
parent 78fe6c306e
commit bd811aac7d
2 changed files with 88 additions and 69 deletions

View file

@ -46,11 +46,11 @@ namespace CodeImp.DoomBuilder
private static string storedtext = string.Empty; private static string storedtext = string.Empty;
private static DebugConsole me; 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; } } public static int Counter { get { return counter; } }
#endregion #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) { Write(type, text, true); }
public static void Write(DebugMessageType type, string text, bool append) public static void Write(DebugMessageType type, string text, bool append)
{ {
if(me != null && me.InvokeRequired) if (General.MainWindow == null)
{ return;
me.Invoke(new Action<DebugMessageType, string, bool>(Write), new object[] { type, text, append }); General.MainWindow.RunOnUIThread(() =>
} {
else if (messages.Count + 1 > MAX_MESSAGES) lock (messages) { messages.RemoveAt(0); }
{ messages.Add(new KeyValuePair<DebugMessageType, string>(type, text));
if(messages.Count + 1 > MAX_MESSAGES) lock (messages) { messages.RemoveAt(0); } if (me != null && (me.filters & type) == type)
messages.Add(new KeyValuePair<DebugMessageType, string>(type, text)); {
if(me != null && (me.filters & type) == type) me.AddMessage(type, text, true, append);
{ }
me.AddMessage(type, text, true, append); });
}
}
} }
public static void Clear() public static void Clear()
{ {
if(me != null && me.InvokeRequired) if (General.MainWindow == null)
{ return;
me.Invoke(new Action(Clear)); General.MainWindow.RunOnUIThread(() =>
} {
else if (me != null) me.console.Clear();
{ messages.Clear();
if(me != null) me.console.Clear(); });
messages.Clear();
}
} }
public static void StartTimer() public static void StartTimer()

View file

@ -282,6 +282,11 @@ namespace CodeImp.DoomBuilder.Windows
//mxd. Hints //mxd. Hints
hintsPanel = new HintsPanel(); hintsPanel = new HintsPanel();
hintsDocker = new Docker("hints", "Help", hintsPanel); hintsDocker = new Docker("hints", "Help", hintsPanel);
// [ZZ]
InvokeTimer.Tick += new EventHandler(InvokeHandler);
InvokeTimer.Interval = 10;
InvokeTimer.Start();
} }
#endregion #endregion
@ -4112,12 +4117,37 @@ namespace CodeImp.DoomBuilder.Windows
#region ================== Threadsafe updates #region ================== Threadsafe updates
Timer InvokeTimer = new Timer();
List<System.Action> InvokeActions = new List<System.Action>();
// this is actually InvokeTimer.Tick handler
void InvokeHandler(object sender, EventArgs e)
{
InvokeTimer.Stop();
List<System.Action> actions = null;
lock (InvokeActions)
{
if (InvokeActions.Count > 0)
{
actions = new List<System.Action>();
actions.AddRange(InvokeActions);
}
}
if (actions == null)
return;
foreach (System.Action action in actions)
action();
InvokeTimer.Start();
}
public void RunOnUIThread(System.Action action) public void RunOnUIThread(System.Action action)
{ {
if (InvokeRequired) if (!InvokeRequired) action();
Invoke(action); else lock (InvokeActions) InvokeActions.Add(action);
else
action();
} }
public void UpdateStatus() public void UpdateStatus()
@ -4198,28 +4228,24 @@ namespace CodeImp.DoomBuilder.Windows
private delegate void SetWarningsCountCallback(int count, bool blink); private delegate void SetWarningsCountCallback(int count, bool blink);
internal void SetWarningsCount(int count, bool blink) internal void SetWarningsCount(int count, bool blink)
{ {
if(this.InvokeRequired) RunOnUIThread(() =>
{ {
SetWarningsCountCallback d = SetWarningsCount; // Update icon, start annoying blinking if necessary
this.Invoke(d, new object[] { count, blink }); if (count > 0)
return; {
} 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 // Update errors count
if(count > 0) warnsLabel.Text = count.ToString();
{ });
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();
} }
//mxd. Bliks warnings indicator //mxd. Bliks warnings indicator
@ -4240,7 +4266,10 @@ namespace CodeImp.DoomBuilder.Windows
if(!blinkTimer.Enabled) return; if(!blinkTimer.Enabled) return;
try try
{ {
this.Invoke(new CallBlink(Blink)); RunOnUIThread(() =>
{
Blink();
});
} catch(ObjectDisposedException) { } //la-la-la. We don't care. } catch(ObjectDisposedException) { } //la-la-la. We don't care.
} }
@ -4465,24 +4494,18 @@ namespace CodeImp.DoomBuilder.Windows
#region ================== Updater (mxd) #region ================== Updater (mxd)
private delegate void UpdateAvailableCallback(int remoterev, string changelog); private delegate void UpdateAvailableCallback(int remoterev, string changelog);
internal void UpdateAvailable(int remoterev, string changelog) internal void UpdateAvailable(int remoterev, string changelog)
{ {
if(this.InvokeRequired) RunOnUIThread(() => {
{ // Show the window
UpdateAvailableCallback d = UpdateAvailable; UpdateForm form = new UpdateForm(remoterev, changelog);
this.Invoke(d, new object[] { remoterev, changelog }); form.FormClosing += delegate
} {
else // Update ignored revision number
{ General.Settings.IgnoredRemoteRevision = (form.IgnoreThisUpdate ? remoterev : 0);
// Show the window };
UpdateForm form = new UpdateForm(remoterev, changelog); form.Show(this);
form.FormClosing += delegate });
{
// Update ignored revision number
General.Settings.IgnoredRemoteRevision = (form.IgnoreThisUpdate ? remoterev : 0);
};
form.Show(this);
}
} }
#endregion #endregion