mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-09-13 06:07:30 -04:00
Reading RunWorkerCompletedEventArgs.Result rethrows any exception from the count DoWork. In the Avalonia async void handler this became an unhandled exception that killed the app during library load (issue #1931). Check e.Cancelled/e.Error first, log once, and degrade to empty stats in both the Avalonia and WinForms backup-count completion handlers. Co-authored-by: rmcrackan <rmcrackan@gmail.com>
111 lines
4.0 KiB
C#
111 lines
4.0 KiB
C#
using ApplicationServices;
|
|
using DataLayer;
|
|
using Dinah.Core.Threading;
|
|
using System.Collections.Generic;
|
|
|
|
namespace LibationWinForms;
|
|
|
|
public partial class Form1
|
|
{
|
|
private readonly System.ComponentModel.BackgroundWorker updateCountsBw = new();
|
|
|
|
protected void Configure_BackupCounts()
|
|
{
|
|
// init formattable
|
|
beginBookBackupsToolStripMenuItem.Format(0);
|
|
beginPdfBackupsToolStripMenuItem.Format(0);
|
|
|
|
LibraryCommands.LibrarySizeChanged += setBackupCounts;
|
|
//Pass null to the runner to get the whole library.
|
|
LibraryCommands.BookUserDefinedItemCommitted += (_, _)
|
|
=> setBackupCounts(null, null);
|
|
|
|
updateCountsBw.DoWork += UpdateCountsBw_DoWork;
|
|
// Register the error logger first so a failed count is logged exactly once, before the
|
|
// display handlers below run and (safely) treat the stats as unavailable.
|
|
updateCountsBw.RunWorkerCompleted += logBackupCountsError;
|
|
updateCountsBw.RunWorkerCompleted += exportMenuEnable;
|
|
updateCountsBw.RunWorkerCompleted += updateBottomStats;
|
|
updateCountsBw.RunWorkerCompleted += update_BeginBookBackups_menuItem;
|
|
updateCountsBw.RunWorkerCompleted += udpate_BeginPdfOnlyBackups_menuItem;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Safely extract the completed <see cref="LibraryCommands.LibraryStats"/>. Returns null when the
|
|
/// background count was cancelled or faulted. Reading <see cref="System.ComponentModel.RunWorkerCompletedEventArgs.Result"/>
|
|
/// directly rethrows any <see cref="System.ComponentModel.RunWorkerCompletedEventArgs.Error"/>, which would otherwise
|
|
/// crash the app; callers must degrade gracefully on null.
|
|
/// </summary>
|
|
private static LibraryCommands.LibraryStats? getLibraryStats(System.ComponentModel.RunWorkerCompletedEventArgs e)
|
|
=> e.Cancelled || e.Error is not null ? null : e.Result as LibraryCommands.LibraryStats;
|
|
|
|
private static void logBackupCountsError(object? _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
|
{
|
|
if (e.Error is not null)
|
|
Serilog.Log.Logger.Error(e.Error, "Failed to update backup counts");
|
|
}
|
|
|
|
private bool runBackupCountsAgain;
|
|
|
|
private void setBackupCounts(object? _, List<LibraryBook>? libraryBooks)
|
|
{
|
|
runBackupCountsAgain = true;
|
|
|
|
if (!updateCountsBw.IsBusy)
|
|
updateCountsBw.RunWorkerAsync(libraryBooks);
|
|
}
|
|
|
|
private void UpdateCountsBw_DoWork(object? sender, System.ComponentModel.DoWorkEventArgs e)
|
|
{
|
|
while (runBackupCountsAgain)
|
|
{
|
|
runBackupCountsAgain = false;
|
|
e.Result = LibraryCommands.GetCounts(e.Argument as IEnumerable<LibraryBook>);
|
|
}
|
|
}
|
|
|
|
private void exportMenuEnable(object? _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
|
{
|
|
var libraryStats = getLibraryStats(e);
|
|
Invoke(() => exportLibraryToolStripMenuItem.Enabled = libraryStats?.HasBookResults is true);
|
|
}
|
|
|
|
private void updateBottomStats(object? _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
|
{
|
|
var libraryStats = getLibraryStats(e);
|
|
statusStrip1.UIThreadAsync(() => backupsCountsLbl.Text = libraryStats?.StatusString ?? "ERROR GETTING STATUS");
|
|
}
|
|
|
|
// update 'begin book and pdf backups' menu item
|
|
private void update_BeginBookBackups_menuItem(object? _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
|
{
|
|
var libraryStats = getLibraryStats(e);
|
|
|
|
var menuItemText
|
|
= libraryStats?.HasPendingBooks is true
|
|
? $"{libraryStats.PendingBooks} remaining"
|
|
: "All books have been liberated";
|
|
menuStrip1.UIThreadAsync(() =>
|
|
{
|
|
beginBookBackupsToolStripMenuItem.Format(menuItemText);
|
|
beginBookBackupsToolStripMenuItem.Enabled = libraryStats?.HasPendingBooks is true;
|
|
});
|
|
}
|
|
|
|
// update 'begin pdf only backups' menu item
|
|
private void udpate_BeginPdfOnlyBackups_menuItem(object? _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
|
{
|
|
var libraryStats = getLibraryStats(e);
|
|
|
|
var menuItemText
|
|
= libraryStats?.pdfsNotDownloaded > 0
|
|
? $"{libraryStats.pdfsNotDownloaded} remaining"
|
|
: "All PDFs have been downloaded";
|
|
menuStrip1.UIThreadAsync(() =>
|
|
{
|
|
beginPdfBackupsToolStripMenuItem.Format(menuItemText);
|
|
beginPdfBackupsToolStripMenuItem.Enabled = libraryStats?.pdfsNotDownloaded > 0;
|
|
});
|
|
}
|
|
}
|