Optimierung des Startvorgangs, lazy load, async im thread pool oder während des Startbildschirms vor dem Mainwindow.
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
2026-09-02 21:46:01 +02:00
parent 94946ffefb
commit 7ef0c95a73
4 changed files with 20 additions and 19 deletions
+14 -12
View File
@@ -52,7 +52,7 @@ public class App : Application
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
private static void ContinueStartup( private static async void ContinueStartup(
IClassicDesktopStyleApplicationLifetime desktop, SplashWindow splash) IClassicDesktopStyleApplicationLifetime desktop, SplashWindow splash)
{ {
// Verschlüsselte Datenbank (13.3.4): Passwort abfragen, bevor die Datenbank // Verschlüsselte Datenbank (13.3.4): Passwort abfragen, bevor die Datenbank
@@ -62,11 +62,10 @@ public class App : Application
var promptVm = new DbPasswordPromptViewModel( var promptVm = new DbPasswordPromptViewModel(
new DatabaseEncryptionService(), AppBootstrapper.ResolveDbPath()); new DatabaseEncryptionService(), AppBootstrapper.ResolveDbPath());
var promptWindow = new DbPasswordPromptWindow { DataContext = promptVm }; var promptWindow = new DbPasswordPromptWindow { DataContext = promptVm };
promptVm.OnUnlocked = password => promptVm.OnUnlocked = async password =>
{ {
AppBootstrapper.DbPassword = password; AppBootstrapper.DbPassword = password;
StartMainApp(desktop, splash); await StartMainAppAsync(desktop, promptWindow);
promptWindow.Close();
}; };
desktop.MainWindow = promptWindow; desktop.MainWindow = promptWindow;
promptWindow.Show(); promptWindow.Show();
@@ -74,10 +73,10 @@ public class App : Application
return; return;
} }
StartMainApp(desktop, splash); await StartMainAppAsync(desktop, splash);
} }
private static void StartMainApp( private static async Task StartMainAppAsync(
IClassicDesktopStyleApplicationLifetime desktop, Window? windowToClose = null) IClassicDesktopStyleApplicationLifetime desktop, Window? windowToClose = null)
{ {
_serviceProvider = AppBootstrapper.BuildServices(); _serviceProvider = AppBootstrapper.BuildServices();
@@ -98,13 +97,16 @@ public class App : Application
var mainVm = Services.GetRequiredService<MainWindowViewModel>(); var mainVm = Services.GetRequiredService<MainWindowViewModel>();
WireCallbacks(mainVm); WireCallbacks(mainVm);
// DI-Singletons werden erst beim ersten Auflösen erzeugt. Ohne dieses explizite // Beide optionalen Erstabgleiche noch unter dem Splashscreen abschließen. Ihre
// Auflösen entstand der Timer des optionalen WebUntis-Abgleichs erst, wenn die // CPU-/Datenbankarbeit läuft innerhalb der Dienste im Threadpool; dadurch öffnet das
// Einstellungen geöffnet oder ein manueller Abruf gestartet wurde. Den Dienst beim // Hauptfenster mit fertigem Datenstand und friert nicht kurz danach ein. Das Auflösen
// Anwendungsstart aktivieren und wie den Jahresplan sofort einmal abgleichen; danach // aktiviert zugleich die periodischen Timer.
// übernimmt sein stündlicher Timer. var initialPolls = new List<Task>();
if (Services.GetService<UntisSyncService>() is { } untisSync) if (Services.GetService<UntisSyncService>() is { } untisSync)
_ = untisSync.PollAsync(); initialPolls.Add(untisSync.PollAsync());
if (Services.GetService<AnnualPlanSyncService>() is { } annualPlanSync)
initialPolls.Add(annualPlanSync.PollAsync());
await Task.WhenAll(initialPolls);
var main = new MainWindow { DataContext = mainVm }; var main = new MainWindow { DataContext = mainVm };
main.EnableWindowSizePersistence(Services.GetRequiredService<WindowSettingsService>()); main.EnableWindowSizePersistence(Services.GetRequiredService<WindowSettingsService>());
@@ -38,7 +38,7 @@ public sealed class AnnualPlanSyncService : IDisposable
public async Task PollAsync() public async Task PollAsync()
{ {
if (!await _gate.WaitAsync(0)) return; if (!await _gate.WaitAsync(0).ConfigureAwait(false)) return;
try try
{ {
var url = _settings.GetIcalUrl(); var url = _settings.GetIcalUrl();
@@ -47,7 +47,7 @@ public sealed class AnnualPlanSyncService : IDisposable
string icsText; string icsText;
try try
{ {
icsText = await _http.GetStringAsync(url); icsText = await _http.GetStringAsync(url).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -59,7 +59,7 @@ public sealed class AnnualPlanSyncService : IDisposable
AnnualPlanPollResult result; AnnualPlanPollResult result;
try try
{ {
result = ProcessIcsText(icsText); result = await Task.Run(() => ProcessIcsText(icsText)).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -67,7 +67,7 @@ public class UntisSyncService : IDisposable
public async Task PollAsync() public async Task PollAsync()
{ {
if (!await _gate.WaitAsync(0)) return; if (!await _gate.WaitAsync(0).ConfigureAwait(false)) return;
try try
{ {
var url = _settings.GetIcalUrl(); var url = _settings.GetIcalUrl();
@@ -76,7 +76,7 @@ public class UntisSyncService : IDisposable
string icsText; string icsText;
try try
{ {
icsText = await _http.GetStringAsync(url); icsText = await _http.GetStringAsync(url).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -88,7 +88,7 @@ public class UntisSyncService : IDisposable
UntisPollResult result; UntisPollResult result;
try try
{ {
result = ProcessIcsText(icsText); result = await Task.Run(() => ProcessIcsText(icsText)).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -170,7 +170,6 @@ public partial class DashboardViewModel : ObservableObject
if (annualPlanSync is not null) if (annualPlanSync is not null)
{ {
annualPlanSync.DataChanged += () => Avalonia.Threading.Dispatcher.UIThread.Post(LoadCalendar); annualPlanSync.DataChanged += () => Avalonia.Threading.Dispatcher.UIThread.Post(LoadCalendar);
_ = annualPlanSync.PollAsync();
} }
LoadDashboardCards(); LoadDashboardCards();
Load(); Load();