Fix possible cross-threading errors with MessageBoxBase

This commit is contained in:
MBucari 2025-07-16 22:57:25 -06:00
parent 4b7939541a
commit 7e79e98771
3 changed files with 36 additions and 7 deletions

View File

@ -107,12 +107,12 @@ namespace LibationAvalonia
} }
private static async Task<DialogResult> ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true) private static async Task<DialogResult> ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
=> await Dispatcher.UIThread.InvokeAsync(async () =>
{ {
owner = owner?.IsLoaded is true ? owner : null; owner = owner?.IsLoaded is true ? owner : null;
var dialog = await Dispatcher.UIThread.InvokeAsync(() => CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition)); var dialog = CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition);
return await DisplayWindow(dialog, owner); return await DisplayWindow(dialog, owner);
} });
private static MessageBoxWindow CreateMessageBox(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true) private static MessageBoxWindow CreateMessageBox(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
{ {

View File

@ -399,8 +399,16 @@ public abstract class ProcessBookViewModelBase : ReactiveObject
const MessageBoxButtons SkipDialogButtons = MessageBoxButtons.AbortRetryIgnore; const MessageBoxButtons SkipDialogButtons = MessageBoxButtons.AbortRetryIgnore;
const MessageBoxDefaultButton SkipDialogDefaultButton = MessageBoxDefaultButton.Button1; const MessageBoxDefaultButton SkipDialogDefaultButton = MessageBoxDefaultButton.Button1;
try
{
return await MessageBoxBase.Show(skipDialogText, "Skip this book?", SkipDialogButtons, MessageBoxIcon.Question, SkipDialogDefaultButton); return await MessageBoxBase.Show(skipDialogText, "Skip this book?", SkipDialogButtons, MessageBoxIcon.Question, SkipDialogDefaultButton);
} }
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "Error showing retry dialog. Defaulting to 'Retry'; action.");
return DialogResult.Retry;
}
}
#endregion #endregion
} }

View File

@ -23,9 +23,6 @@ namespace LibationWinForms
{ {
Task<List<LibraryBook>> libraryLoadTask; Task<List<LibraryBook>> libraryLoadTask;
LibationUiBase.Forms.MessageBoxBase.ShowAsyncImpl = (owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition) =>
Task.FromResult((LibationUiBase.Forms.DialogResult)MessageBox.Show(owner as IWin32Window, message, caption, (MessageBoxButtons)buttons, (MessageBoxIcon)icon, (MessageBoxDefaultButton)defaultButton));
try try
{ {
//// Uncomment to see Console. Must be called before anything writes to Console. //// Uncomment to see Console. Must be called before anything writes to Console.
@ -90,7 +87,31 @@ namespace LibationWinForms
var form1 = new Form1(); var form1 = new Form1();
form1.Load += async (_, _) => await form1.InitLibraryAsync(await libraryLoadTask); form1.Load += async (_, _) => await form1.InitLibraryAsync(await libraryLoadTask);
LibationUiBase.Forms.MessageBoxBase.ShowAsyncImpl = ShowMessageBox;
Application.Run(form1); Application.Run(form1);
#region Message Box Handler for LibationUiBase
Task<LibationUiBase.Forms.DialogResult> ShowMessageBox(
object owner,
string message,
string caption,
LibationUiBase.Forms.MessageBoxButtons buttons,
LibationUiBase.Forms.MessageBoxIcon icon,
LibationUiBase.Forms.MessageBoxDefaultButton defaultButton,
bool _)
{
var result = form1.Invoke(() =>
MessageBox.Show(
owner as IWin32Window ?? form1,
message,
caption,
(MessageBoxButtons)buttons,
(MessageBoxIcon)icon,
(MessageBoxDefaultButton)defaultButton));
return Task.FromResult((LibationUiBase.Forms.DialogResult)result);
}
#endregion;
} }
private static void RunInstaller(Configuration config) private static void RunInstaller(Configuration config)