Wrap all accesses to cancellation token source in PackageItemViewModel in try-catch blocks to handle ObjectDisposedException gracefully
Wrap all accesses to _cancellationTokenSource.Token in try-catch blocks to handle ObjectDisposedException gracefully
Bug
Fixes: https://github.com/NuGet/Client.Engineering/issues/3499
Description
The PackageItemViewModel class was throwing ObjectDisposedException when code attempted to access the CancellationTokenSource after the ViewModel had been disposed. This exception was being logged as a fault in telemetry.
Root Cause
The issue occurred when:
- The PackageItemViewModel's
Dispose()method was called, which disposed the_cancellationTokenSource - Async methods that had already started (or were about to start) attempted to access
_cancellationTokenSource.Token - Accessing the
Tokenproperty of a disposed CancellationTokenSource throwsObjectDisposedException
Solution
The fix wraps all accesses to _cancellationTokenSource.Token in try-catch blocks to handle ObjectDisposedException gracefully. When the CancellationTokenSource is disposed:
- GetVersionsAsync methods: Return empty collections instead of throwing
- Async operations (ReloadPackageVersionsAsync, RunOperationAsync): Exit gracefully as if cancelled
- GetDetailedPackageSearchMetadataAsync: Throws OperationCanceledException (which is already handled by callers)
- UpdateInstalledPackagesVulnerabilities: Does not start new operations
This approach ensures that:
- ObjectDisposedException is never propagated to telemetry
- The behavior is semantically correct (treating disposed state as cancelled)
- No existing functionality is broken
PR Checklist
- [x] Meaningful title, helpful description and a linked NuGet/Home issue
- [x] Added tests
- [ ] ~Link to an issue or pull request to update docs if this PR changes settings, environment variables, new feature, etc.~
This PR has been automatically marked as stale because it has no activity for 7 days. It will be closed if no further activity occurs within another 7 days of this comment. If it is closed, you may reopen it anytime when you're ready again, as long as you don't delete the branch.