fix: ensure consistent schedulers across threads by removing ThreadStatic in RxSchedulers #4192
+0
−2
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
Remove
ThreadStaticfromRxSchedulers.MainThreadSchedulerandRxSchedulers.TaskpoolSchedulerso that schedulers are process-wide singletons instead of thread-local values.Motivation / Context
When
RxSchedulerswas introduced, bothMainThreadSchedulerandTaskpoolSchedulerwere marked[ThreadStatic]. Unlike the pre-splitRxApp(where only the unit test fields were thread-static), this made the production schedulers thread-local. The result:RxSchedulers.MainThreadScheduler/TaskpoolSchedulerfrom different threads could return different instances.This regressed the previous behavior where production schedulers were app-global, and only unit-test overrides were thread-scoped.
What’s changed
Removed
[ThreadStatic]from:Retained the existing
lock-based lazy init to ensure thread-safe, single-instance initialization:MainThreadSchedulerdefaults toDefaultScheduler.Instance.TaskpoolSchedulerdefaults toTaskPoolScheduler.Default(orDefaultScheduler.InstanceinPORTABLE).No public API changes.
Current behavior (before this PR)
RxSchedulers.MainThreadScheduler/TaskpoolSchedulerare thread-local: each thread can see an independent value, and new threads may “re-initialize” to default unexpectedly.New behavior (after this PR)
RxSchedulers.MainThreadScheduler/TaskpoolSchedulerare process-wide singletons:RxAppsemantics remain unchanged:RxApponly, preserving historical test behavior.Risks / Breaking changes
RxSchedulerswith developer expectations (global, stable schedulers in production code).RxSchedulersmay observe different (correct) behavior now; this is considered a bug fix.How I verified
Manual sanity checks:
RxSchedulers.MainThreadScheduleron a background thread; read from UI/main thread → same instance.lock).Ensured
RxAppunit-test behavior remains intact (thread-static kept where it was originally:_unitTest*fields).Repro (old bug)
Documentation impact
None for public API. Internal behavior now matches historical RxUI expectations:
RxSchedulersfor simple, app-global schedulers.RxAppwhen you need test-runner detection and per-thread unit test overrides.Related
RxSchedulers: production fields gained[ThreadStatic], diverging from the originalRxApppattern where only unit test fields were thread-static.Checklist
RxApp