Repository navigation
Dispose a model's items even when its collection is cleared first - #833
Merged
Merged
Conversation
With an application running, DisposableCollection.Dispose queues the disposal of its items on the dispatcher (#373), and DisposableModelBase clears the collection as soon as that call returns (#639). The queued callback then enumerated an empty collection, so a DisposableModelBase disposed nothing while MS-DIAL ran. A file model's .dcl reader, for one, stayed open after its dataset closed, until a finalizer closed it. DisposableCollection now copies the items before it queues their disposal. LcmsAnalysisModelWithoutRawTests failed in Debug because it never disposed the file model that owns the .dcl reader, so Cleanup could not delete sample.dcl. In Release the JIT let the file model die early and the test's own GC.Collect finalized the stream. The test now disposes the file model as the dataset would, waits for the dispatcher, and checks that neither the .dcl nor the .pai2 is open before any collection. A new AnalysisFileBeanModelTests case checks that ReleaseMSDecLoader and Dispose close the .dcl while an application runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 15, 2026
Merged
The test guards against the old freeze, in which reading the missing raw data waited 5 s before each of its retries (BaseDataProvider). Two seconds also failed a cold CI runner that took 2.8 s to open the sample without any retry (PR #835's PR Check). Below 5 s still fails any retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Added 0df2b42 after checking why #832, #834, #835 and #836 fail PR Check. All four fail on the one test this PR fixes,
The bound exists to catch the old freeze, where reading the missing raw data slept 5 s before each retry ( Once this is merged, the other four branches need master merged in (or a re-run) to pick it up. 🤖 Generated with Claude Code |
htsugawa
pushed a commit
that referenced
this pull request
Oct 16, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
htsugawa
pushed a commit
that referenced
this pull request
Oct 16, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
htsugawa
pushed a commit
that referenced
this pull request
Oct 16, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
htsugawa
pushed a commit
that referenced
this pull request
Oct 16, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
LcmsAnalysisModelWithoutRawTests.ASampleWithoutRawDataOpensFromWhatTheProjectStores(added in #829) fails in Debug: its cleanup cannot deletesample.dcl. There were two causes:AnalysisFileBeanModelowns and caches the.dclreader (MSDecLoader).LcmsAnalysisModelborrows that reader throughMsDecSpectrumFromFileLoader, and the dataset'sAnalysisFileBeanModelCollectiondisposes it. The test plays the dataset's part but never disposed the file model. In Release the JIT let the local die early, so the test's ownGC.Collect()finalized theFileStreamand the test passed by accident. In Debug the local stays alive until the method returns, so the handle was still open whenCleanupran.DisposableCollection. When I made the test dispose the file model, the.dclstill stayed open. While an application runs,DisposableCollection.Disposequeues its items' disposal on the dispatcher (InvokeAsync, Background, since Release msidal5.3 #373).DisposableModelBase.Disposethen callsDisposables.Clear()as soon as that call returns (since Implement analysis pipeline and UI for TIMS-off imaging #639). The queued callback enumerates the collection when it runs, finds it empty, and disposes nothing. So since Implement analysis pipeline and UI for TIMS-off imaging #639 aDisposableModelBasedisposed none of its items while MS-DIAL ran. WhenDisposewas called off the UI thread, the clear could also race the enumeration.The no-raw browsing path does not leak a handle of its own. I checked this with exclusive-open probes at each step:
.dclopen.pai2openLcmsAnalysisModelLcmsAnalysisModel.Dispose()file.ReleaseMSDecLoader()file.Dispose()with an application running, before the fixChanges
DisposableCollection: copy the items before queuing their disposal. Disposal still happens on the dispatcher at Background priority, as Release msidal5.3 #373 intended, andClear()still drops the references, as Implement analysis pipeline and UI for TIMS-off imaging #639 intended.LcmsAnalysisModelWithoutRawTests:.dclnor the.pai2is still open. The check runs before anyGC.Collect, so a finalizer cannot hide a leak.AnalysisFileBeanModelTests.ReleasingTheLoaderOrDisposingTheModelClosesTheDeconvolutionFile(new) runs with an application. It checks thatReleaseMSDecLoader()(used before reprocessing rewrites the.dcl) andDispose()both close the.dcl.Utility/TestApplicationandUtility/TestFilesare shared test helpers.TestApplicationis the STA application thatLcmsAnalysisModelWithoutRawTestsused to build privately, plus a wait for Background-priority dispatcher work.Behaviour change to review
82 source files define classes that derive from
DisposableModelBase. Since #639, none of them disposed theirDisposableswhile the GUI ran; they now do, deferred to the dispatcher as before #639. This is the intended behaviour, but an object that is registered withAddTo(Disposables)and still used elsewhere would now be disposed where it previously was not. Such double-ownership bugs could have been introduced since September 2025. I have not exercised the running GUI with this change, only the test suites below.Tests
Built with
dotnet(net48), default NuGet sources, in the worktreeMsdialWorkbench-dcl-lock.IOException: ... 'sample.dcl' because it is being used by another process) and passes in Release. The new and adjusted tests fail in both Debug and Release on the.dclstill being open afterDispose().MsdialGuiAppTestspassed 145/145 in Debug and in Release, three full runs each before a final helper refactor and one each after it. The target test also passes alone in both.CommonMVVMTestspassed 16/16.🤖 Generated with Claude Code