[wasm] Request: Option to keep .NET main thread on browser UI thread when threading is enabled
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
When `true` is set, the .NET runtime moves entirely to a background Web Worker (the "Deputy Thread" model). This makes `DotNet.invokeMethod` — synchronous JS-to-.NET calls — impossible, because the browser's UI thread cannot block while waiting for a response from a worker.
I'm requesting a supported configuration option that enables .NET threading (thread pool, `Task.Run`, `System.Threading`) while keeping the main .NET entry point on the browser's UI thread.
### Background
I maintain the [SpawnDev.BlazorJS](https://github.com/LostBeard/SpawnDev.BlazorJS) ecosystem — 41 NuGet packages, 323,000+ total downloads — which provides typed C# wrappers for JavaScript APIs in Blazor WebAssembly. This library depends on synchronous JS-to-.NET interop (`DotNet.invokeMethod`) because the JavaScript specification requires synchronous handling in many scenarios:
- `event.preventDefault()` must be called synchronously within the handler
- `event.stopImmediatePropagation()` — same constraint
- `beforeunload` requires a synchronous return value
- Synchronous property getters on JS objects
- Callback-driven APIs that expect synchronous returns
These are not edge cases. These are fundamental browser APIs that cannot be handled asynchronously.
### Proposed Behavior
A configuration like:
```xml
true
true
```
When enabled:
- `Program.Main` executes on the browser's UI thread (as it does today without threading)
- Synchronous JS interop (`DotNet.invokeMethod`, `[JSExport]` with sync signatures) works normally
- `Task.Run`, `ThreadPool`, and `new Thread()` dispatch to background Web Workers
- Blocking primitives (`lock`, `Monitor.Enter`, `Thread.Sleep`) work on background threads but throw on the UI thread (this is already the browser's constraint)
This is architecturally the same model that [SpawnDev.BlazorJS.WebWorkers](https://www.nuget.org/packages/SpawnDev.BlazorJS.WebWorkers) (90,000+ downloads) has used successfully for years: main .NET on the UI thread, heavy work dispatched to workers explicitly.
### Why This Matters
Without this option, any .NET library that provides synchronous JavaScript interop is broken when threading is enabled. This affects:
- SpawnDev.BlazorJS and its 41-package ecosystem (WebRTC, WebGPU, WebTorrent, Canvas, Crypto, etc.)
- Any third-party library wrapping synchronous JS APIs
- Any application handling DOM events that require synchronous responses
The Deputy Thread model is valuable for applications that prioritize background computation over DOM fidelity. But it should not be the **only** option. Developers who need synchronous JS interop should be able to opt into threading without losing it.
### Related Issues
- dotnet/aspnetcore#54365 — "Make Blazor WebAssembly work on multithreaded runtime"
### Environment
- .NET 10
- Blazor WebAssembly
- All modern browsers (Chrome, Edge, Firefox, Safari)
Contributor guide
Assessment
This issue has not been assessed yet.