diff --git a/WinSyncScroll/ViewModels/MainViewModel.cs b/WinSyncScroll/ViewModels/MainViewModel.cs index 1dbbabc..a36b5c8 100644 --- a/WinSyncScroll/ViewModels/MainViewModel.cs +++ b/WinSyncScroll/ViewModels/MainViewModel.cs @@ -545,29 +545,16 @@ public void HandleWindowClosing() } } - public void Dispose() + private void WaitForTaskCompletion(Task? task, string taskName, TimeSpan timeout) { - AppState = AppState.NotRunning; - try - { - _cancellationTokenSource.Cancel(); - } - catch (Exception e) - { - _logger.LogError(e, "Error cancelling the cancellation token source"); - } - - // Wait for tasks to complete before disposing resources - // Using Task.Wait in Dispose is acceptable as this is a shutdown scenario - // and we need to ensure tasks complete before disposing underlying resources -#pragma warning disable VSTHRD002 // Synchronously waiting is acceptable in Dispose method +#pragma warning disable VSTHRD002 // Synchronously waiting is acceptable in shutdown scenarios try { - if (_updateMouseHookRectsLoopTask is not null - && !_updateMouseHookRectsLoopTask.IsCompleted - && !_updateMouseHookRectsLoopTask.Wait(TimeSpan.FromSeconds(5))) + if (task is not null + && !task.IsCompleted + && !task.Wait(timeout)) { - _logger.LogWarning("Update mouse hook rects loop task did not complete within timeout"); + _logger.LogWarning("{TaskName} did not complete within timeout", taskName); } } catch (AggregateException ae) @@ -576,47 +563,38 @@ public void Dispose() { if (ex is OperationCanceledException) { - _logger.LogDebug("Update mouse hook rects loop was cancelled"); + _logger.LogDebug("{TaskName} was cancelled", taskName); return true; } - _logger.LogError(ex, "Error waiting for update mouse hook rects loop task"); + _logger.LogError(ex, "Error waiting for {TaskName} to complete", taskName); return true; }); } catch (Exception e) { - _logger.LogError(e, "Error disposing update mouse hook rects loop task"); + _logger.LogError(e, "Error waiting for {TaskName} to complete", taskName); } +#pragma warning restore VSTHRD002 + } + public void Dispose() + { + AppState = AppState.NotRunning; try { - if (_mouseEventProcessingLoopTask is not null - && !_mouseEventProcessingLoopTask.IsCompleted - && !_mouseEventProcessingLoopTask.Wait(TimeSpan.FromSeconds(5))) - { - _logger.LogWarning("Mouse event processing loop task did not complete within timeout"); - } - } - catch (AggregateException ae) - { - ae.Handle(ex => - { - if (ex is OperationCanceledException) - { - _logger.LogDebug("Mouse event processing loop was cancelled"); - return true; - } - - _logger.LogError(ex, "Error waiting for mouse event processing loop task"); - return true; - }); + _cancellationTokenSource.Cancel(); } catch (Exception e) { - _logger.LogError(e, "Error disposing mouse event processing loop task"); + _logger.LogError(e, "Error cancelling the cancellation token source"); } -#pragma warning restore VSTHRD002 + + // Wait for tasks to complete before disposing resources + // Using Task.Wait in Dispose is acceptable as this is a shutdown scenario + // and we need to ensure tasks complete before disposing underlying resources + WaitForTaskCompletion(_updateMouseHookRectsLoopTask, "Update mouse hook rects loop task", TimeSpan.FromSeconds(5)); + WaitForTaskCompletion(_mouseEventProcessingLoopTask, "Mouse event processing loop task", TimeSpan.FromSeconds(5)); // Dispose tasks after they have completed _updateMouseHookRectsLoopTask?.Dispose();