Commit 7f1f516
fix(selftest): drain dispatcher after UpdateLayout in Harness.Render
Local 10x sweeps of the SelfTests suite flake at ~60% (6/10 runs failed),
clustered in NativeDocking_* fixtures whose pane bodies are hosted in a
TabView. The same suite is stable on CI.
Root cause: Harness.Render() did `WaitForIdleAsync() → UpdateLayout() →
Task.Delay(16)`. When Reactor reports idle, WaitForIdleAsync short-circuits
without pumping the dispatcher (the comment at ReactorHost.cs:910 already
flags this: "Returning early here is the classic flake source"). That left
16ms wall-clock as the only safety net for WinUI work that UpdateLayout()
itself scheduled — notably TabView's lazy ContentPresenter realization for
the selected tab, posted at Normal priority.
CI dispatchers run with steady load → 16ms always covered it. Local boxes
(IDE, file watchers, AV) introduced enough jitter that the post-Render
visual-tree probe occasionally lost the race. Failure signature was the
selected pane body / Memo subtree returning null from FindText, which then
cascaded across every assertion in the affected fixture.
Fix: yield once at Low priority between two UpdateLayout() calls. The
first layout schedules content-realization onto the dispatcher; the Low
yield drains it (guaranteed, not timing-dependent); the second layout
arranges the just-realized content. The trailing 16ms Task.Delay is now
just compositor breathing room rather than the entire safety margin.
Same pattern WaitForIdleAsync uses internally and what the no-host
fallback already did — pulled up so the host-present path benefits too.
Verified with 3 local 10x sweeps:
before: 4/10 clean, 5 distinct flaky fixtures, top offender 3/10
v1 fix: 7/10 clean (yield before UpdateLayout — wrong order, didn't
drain layout-spawned work)
final: 10/10 clean, 0 flakes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 836c301 commit 7f1f516
1 file changed
Lines changed: 24 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
229 | 229 | | |
230 | 230 | | |
231 | 231 | | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | 232 | | |
241 | | - | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
242 | 257 | | |
243 | 258 | | |
244 | 259 | | |
| |||
0 commit comments