Fix TrayService singleton resource leak on app shutdown#79
Conversation
…ktop.Exit event Agent-Logs-Url: https://github.com/murapadev/NeuralDeck/sessions/18ac77e2-1364-4719-8a06-6a7c28692cc7 Co-authored-by: murapadev <10557163+murapadev@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Wires TrayService.Dispose() into Avalonia’s desktop application shutdown so the tray icon/menu resources are released during app exit.
Changes:
- Subscribe to
IClassicDesktopStyleApplicationLifetime.ExitinApp.OnFrameworkInitializationCompleted(). - Dispose
TrayService.Instancewhen the desktop lifetime exits.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Dispose tray resources on exit; handler lifetime matches application lifetime. | ||
| desktop.Exit += (s, e) => TrayService.Instance.Dispose(); |
There was a problem hiding this comment.
Hooking TrayService disposal to desktop.Exit only runs on Avalonia’s normal shutdown path. The app also calls Environment.Exit(0) from the tray "Quit" menu (Services/TrayService.cs), which will bypass desktop.Exit and can still leave the tray icon/resources un-disposed. To match the PR description (“on every app exit”), route that quit action through the normal lifetime shutdown (or explicitly dispose TrayService before calling Environment.Exit).
, #79) - MainWindowViewModel: implement IDisposable, dispose ChatViewModel - ShortcutService: add IDisposable interface declaration - App.OnExit: dispose TrayService, ShortcutService, MainWindowViewModel Cherry-picked from copilot branches: 8be25e3 (TrayService), b353ef1 (ShortcutService), 0f80c4d (ChatViewModel)
TrayServiceimplementsDispose()to release the tray icon, context menu, and associated resources, but it was never called — causing those resources to leak on every app exit.Changes
App.axaml.cs: Subscribe todesktop.Exitto invokeTrayService.Instance.Dispose()during the app shutdown sequence.TrayService.Dispose()already handles hiding the icon, nulling the menu, callingTrayIcon.Dispose(), and resetting internal state — this change simply ensures it's wired into the shutdown path.