Stop the STA dispatcher shutdown killing a theory's later rows - #609
Open
kellylford wants to merge 1 commit into
Open
Stop the STA dispatcher shutdown killing a theory's later rows#609kellylford wants to merge 1 commit into
kellylford wants to merge 1 commit into
Conversation
Xunit.StaFact gives each test METHOD a fresh STA thread, but every data row of one [StaTheory] shares that thread. Measured directly: both rows of a two-row StaTheory report the same managed thread id, while each StaFact gets its own. ShutDownStaDispatcherAttribute runs after every test case, so it shut that thread's Dispatcher down after the FIRST row. The remaining rows then ran on a thread whose Dispatcher was dead, and their first WPF operation threw "Cannot perform requested operation because the Dispatcher shut down". That is how AccountDialogHintTests.TheSmtpSslHintNamesBothPorts failed on its second row while passing on its first - reproducibly, 1 in 16, whenever those classes were run as a subset. It hid in full-suite runs because the two rows happened to be scheduled so that the failure did not surface, which is the worst shape for a bug like this: it looks like flakiness in whatever else was running. Shut down after the LAST row instead. The issue #211 protection is unchanged - the thread still never outlives its Dispatcher - and the rows in between keep a working one. Rows are counted because xUnit exposes no "is this the last case" flag and IXunitTestMethod has no test-case collection to ask; when the count cannot be worked out (any data source other than [InlineData], whose rows are only known after running it) the old behaviour stands, since leaking a Dispatcher onto a dying thread is the hazard #211 is about. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kellylford
temporarily deployed
to
azure-signing
August 22, 2026 04:08 — with
GitHub Actions
Inactive
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.
Xunit.StaFactgives each test method a fresh STA thread, but every data row of one[StaTheory]shares that thread. Measured directly with a probe: both rows of a two-rowStaTheoryreport the same managed thread id, while eachStaFactgets its own.ShutDownStaDispatcherAttributeruns after every test case, so it shut that thread'sDispatcherdown after the first row. The remaining rows then ran on a thread whoseDispatcherwas dead, and their first WPF operation threw:That is how
AccountDialogHintTests.TheSmtpSslHintNamesBothPortsfailed on its second row while passing on its first — reproducibly, 1 in 16, every time those classes were run as a subset:It hides in full-suite runs, which is the worst shape for a bug like this: it looks like flakiness in whatever else happened to be running.
The fix
Shut down after the last row instead of after every one. The issue #211 protection is unchanged — the thread still never outlives its
Dispatcher— and the rows in between keep a working one.Rows are counted rather than detected: xUnit exposes no "is this the last case" flag, and
IXunitTestMethodhas no test-case collection to ask (checked its full property surface). When the count cannot be worked out — any data source other than[InlineData], whose rows are only known after running it — the old behaviour stands, since leaking aDispatcheronto a dying thread is exactly the hazard #211 is about.Verification
[StaTheory]methods exist in the suite today, but this removes the trap for any future one whose later rows touch WPF — which fails silently and looks like someone else's flake.🤖 Generated with Claude Code