@@ -375,6 +375,7 @@ private async void StartAutoRefreshLoop(int intervalSeconds)
375375 {
376376 await Task . Delay ( TimeSpan . FromSeconds ( intervalSeconds ) , cts . Token ) ;
377377 if ( cts . Token . IsCancellationRequested ) break ;
378+ if ( _isRefreshing ) continue ;
378379
379380 try
380381 {
@@ -384,6 +385,11 @@ private async void StartAutoRefreshLoop(int intervalSeconds)
384385 FooterText . Text = $ "Last refresh: { DateTime . Now : yyyy-MM-dd HH:mm:ss} | Server: { _serverConnection . DisplayName } ";
385386 Logger . Info ( $ "Auto-refresh completed in { sw . ElapsedMilliseconds } ms for { _serverConnection . DisplayName } ") ;
386387 }
388+ catch ( OperationCanceledException ) when ( ! cts . Token . IsCancellationRequested )
389+ {
390+ // SQL query cancelled or timed out, but our loop CTS is still alive — keep going
391+ Logger . Error ( $ "Auto-refresh query cancelled for { _serverConnection . DisplayName } , continuing loop") ;
392+ }
387393 catch ( Exception ex ) when ( ex is not OperationCanceledException )
388394 {
389395 Logger . Error ( $ "Auto-refresh error: { ex . Message } ", ex ) ;
@@ -393,13 +399,15 @@ private async void StartAutoRefreshLoop(int intervalSeconds)
393399 }
394400 catch ( OperationCanceledException )
395401 {
396- // Normal shutdown
402+ Logger . Info ( $ "Auto-refresh loop stopped for { _serverConnection . DisplayName } " ) ;
397403 }
398404 }
399405
400406 private void ServerTab_Unloaded ( object sender , RoutedEventArgs e )
401407 {
402- _autoRefreshCts ? . Cancel ( ) ;
408+ // Don't cancel auto-refresh on tab switch — WPF fires Unloaded when
409+ // a TabItem is deselected, not just when the control is destroyed.
410+ // The loop is lightweight and should keep ticking in the background.
403411 _autoRefreshTimer ? . Stop ( ) ;
404412 _autoRefreshTimer = null ;
405413
0 commit comments