Forge
markdowndeeb25a2
1<!-- English translation of adr/0004-ui-thread-marshaling.md. Canonical Russian: ../../adr/0004-ui-thread-marshaling.md -->
2
3# ADR 0004: Marshalling UI updates via IUiScheduler
4
5**Status:** Accepted (implementation plan - strangler)
6**Date:** 2026-04-02 (retrospective)
7## Related ADRs
8
9| ADR | Role |
10|-----|------|
11| [0007](0007-signals-coupling-and-ui-backpressure.md) | Signals, loose coupling and UI relief |
12
13### Outside ADR
14
15| Document | Role |
16|----------|------|
17| [architecture-migration.md](../architecture-migration.md) | architecture migration |
18| [architecture-policy.md](../../architecture-policy.md) | architecture policy |
19
20---
21## Context
22
23The IDE has many asynchronous sources (assembly, MCP, LSP, etc.). Spreading `Post`/`Invoke` throughout the code complicates maintenance and increases the risk of accessing the UI from a source other than the UI thread.
24
25## Solution
26
27ViewModel and UI updates after running in the background whenever possible go through **one consistent point** of marshaling: **`IUiScheduler`** and **`UiScheduler.Default`** (implementation on `Dispatcher.UIThread`), rather than arbitrary dispatcher calls throughout the code.
28
29Point queues and batching for overloaded data streams - separately, where necessary (see [ADR 0007](0007-signals-coupling-and-ui-backpressure.md)).
30
31## Consequences
32
33- The new code follows this rule; the existing one migrates gradually.
34- The order of implementation in the code is in [architecture-migration.md](../architecture-migration.md) (phase 5).
35
36## Rejected alternatives
37
38- Leaving marshaling completely spread out across the code without an agreed-upon point is rejected in favor of predictability and review.
View only · write via MCP/CIDE