Severity: Warning
Files and lines:
src/Servy.Manager/Views/MainWindow.xaml.cs lines 49, 59, 105, 136, 155
src/Servy.Manager/Views/ConsoleView.xaml.cs lines 196, 217
src/Servy.Manager/Views/PerformanceView.xaml.cs lines 33, 54
src/Servy.Manager/Views/DependenciesView.xaml.cs lines 33, 54
Description:
Eleven WPF event handlers across four code-behind files are declared private async void. When any await inside them throws, the exception is raised on the SynchronizationContext; by default this either terminates the WPF app via DispatcherUnhandledException or — depending on wiring — disappears. Either way the failure is not observable on a returned Task and is hard to correlate with the originating user gesture (tab switch, Window_Loaded, SearchTextBox_KeyDown, Menu_ConfigClik).
// MainWindow.xaml.cs:155
private async void MainTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try { ... } catch (Exception ex) { ... }
}
Some handlers already have a defensive try/catch, but several (e.g. Window_Loaded calling await vm.SearchCommand.ExecuteAsync(null)) do not, and even where a catch exists the handler still fundamentally can't surface its completion/failure to callers or tests.
Suggested fix:
Prefer ICommand bindings so the async work lives on the ViewModel (AsyncCommand/RelayCommand<T>), which gives you an awaitable Task for testing and exception routing. Where a code-behind handler is unavoidable, route through a tiny helper:
private void Window_Loaded(object sender, RoutedEventArgs e) => _ = Window_LoadedAsync(sender, e);
private async Task Window_LoadedAsync(object sender, RoutedEventArgs e)
{
try { if (DataContext is MainViewModel vm) await vm.SearchCommand.ExecuteAsync(null); }
catch (Exception ex) { Logger.Error(nameof(Window_LoadedAsync), ex); }
}
Severity: Warning
Files and lines:
src/Servy.Manager/Views/MainWindow.xaml.cslines 49, 59, 105, 136, 155src/Servy.Manager/Views/ConsoleView.xaml.cslines 196, 217src/Servy.Manager/Views/PerformanceView.xaml.cslines 33, 54src/Servy.Manager/Views/DependenciesView.xaml.cslines 33, 54Description:
Eleven WPF event handlers across four code-behind files are declared
private async void. When any await inside them throws, the exception is raised on theSynchronizationContext; by default this either terminates the WPF app viaDispatcherUnhandledExceptionor — depending on wiring — disappears. Either way the failure is not observable on a returnedTaskand is hard to correlate with the originating user gesture (tab switch, Window_Loaded, SearchTextBox_KeyDown, Menu_ConfigClik).Some handlers already have a defensive try/catch, but several (e.g.
Window_Loadedcallingawait vm.SearchCommand.ExecuteAsync(null)) do not, and even where a catch exists the handler still fundamentally can't surface its completion/failure to callers or tests.Suggested fix:
Prefer
ICommandbindings so the async work lives on the ViewModel (AsyncCommand/RelayCommand<T>), which gives you an awaitable Task for testing and exception routing. Where a code-behind handler is unavoidable, route through a tiny helper: