@@ -36,6 +36,7 @@ public partial class MainWindow : Window
3636 private CancellationTokenSource ? _backgroundCts ;
3737 private SystemTrayService ? _trayService ;
3838 private readonly Dictionary < string , TabItem > _openServerTabs = new ( ) ;
39+ private readonly Dictionary < string , ( Action < int , int , DateTime ? > AlertCounts , Action < int > ApplyTimeRange , Func < Task > ManualRefresh ) > _tabEventHandlers = new ( ) ;
3940 private readonly Dictionary < string , bool > _previousConnectionStates = new ( ) ;
4041 private readonly Dictionary < string , bool > _previousCollectorErrorStates = new ( ) ;
4142 private readonly Dictionary < string , DateTime > _lastCpuAlert = new ( ) ;
@@ -530,15 +531,13 @@ private async void ConnectToServer(ServerConnection server)
530531 Content = serverTab
531532 } ;
532533
533- /* Subscribe to alert counts for badge updates */
534+ /* Subscribe to events — store handlers so we can unsubscribe on tab close */
534535 var serverId = server . Id ;
535- serverTab . AlertCountsChanged + = ( blockingCount , deadlockCount , latestEventTime ) =>
536+ Action < int , int , DateTime ? > alertHandler = ( blockingCount , deadlockCount , latestEventTime ) =>
536537 {
537538 Dispatcher . Invoke ( ( ) => UpdateTabBadge ( tabHeader , serverId , blockingCount , deadlockCount , latestEventTime ) ) ;
538539 } ;
539-
540- /* Subscribe to "Apply to All" time range propagation */
541- serverTab . ApplyTimeRangeRequested += ( selectedIndex ) =>
540+ Action < int > timeRangeHandler = ( selectedIndex ) =>
542541 {
543542 Dispatcher . Invoke ( ( ) =>
544543 {
@@ -551,9 +550,7 @@ private async void ConnectToServer(ServerConnection server)
551550 }
552551 } ) ;
553552 } ;
554-
555- /* Re-collect on-load data (config, trace flags) when refresh button is clicked */
556- serverTab . ManualRefreshRequested += async ( ) =>
553+ Func < Task > refreshHandler = async ( ) =>
557554 {
558555 if ( _collectorService != null )
559556 {
@@ -572,6 +569,11 @@ private async void ConnectToServer(ServerConnection server)
572569 }
573570 } ;
574571
572+ serverTab . AlertCountsChanged += alertHandler ;
573+ serverTab . ApplyTimeRangeRequested += timeRangeHandler ;
574+ serverTab . ManualRefreshRequested += refreshHandler ;
575+ _tabEventHandlers [ server . Id ] = ( alertHandler , timeRangeHandler , refreshHandler ) ;
576+
575577 _openServerTabs [ server . Id ] = tabItem ;
576578 ServerTabControl . Items . Add ( tabItem ) ;
577579 ServerTabControl . SelectedItem = tabItem ;
@@ -793,7 +795,20 @@ private void CloseServerTab(string serverId)
793795 {
794796 if ( tab . Content is ServerTab serverTab )
795797 {
798+ /* Unsubscribe event handlers to prevent memory leaks */
799+ if ( _tabEventHandlers . TryGetValue ( serverId , out var handlers ) )
800+ {
801+ serverTab . AlertCountsChanged -= handlers . AlertCounts ;
802+ serverTab . ApplyTimeRangeRequested -= handlers . ApplyTimeRange ;
803+ serverTab . ManualRefreshRequested -= handlers . ManualRefresh ;
804+ _tabEventHandlers . Remove ( serverId ) ;
805+ }
806+
796807 serverTab . StopRefresh ( ) ;
808+ serverTab . DisposeChartHelpers ( ) ;
809+
810+ /* Clear delta cache for this server to free memory */
811+ _collectorService ? . DeltaCalculator ? . ClearServer ( serverTab . ServerId ) ;
797812 }
798813
799814 ServerTabControl . Items . Remove ( tab ) ;
0 commit comments