Skip to content

[tracking] Experimental WebAssembly multithreading support #68162

Open

Description

@lambdageek

This is a tracking issue for adding experimental support for WebAssembly multi-threading to the browser-wasm runtime pack.

High Level Goals

  • The threading runtime should be distributed in the same browser-wasm runtime pack The threading runtime is in a separate .multithread. runtime pack variant. The WASM SDK chooses the correct runtime pack variant based on project properties.
  • Threading should be opt-in only
  • The wasm bindings and runtime are thread-safe and co-op GC aware

Completed in .NET 7 RC2

The wasm-experimental workload supports threading using <WasmEnableThreads>true</WasmEnableThreads> in interp and AOT configurations when using the wasmbrowser workload. Blazor does not support threading in .NET 7

Tracking

SDK:

CI testing:

  • Need a way to skip tests on single threaded / multi-threaded wasm configs.
  • Add tests. (src/libraries). Maybe add some convenient way to add ProjectReferences to the multi-threaded ref assemblies (the roll-up Microsoft.NET.WebAssembly.Threading.proj doesn't seem to work) and run the normal runtime tests.

Libraries and Interop:

Runtime and codegen:

Issues:

Done

On the branch:

  • put all modifications under conditionals
    • The runtime build should be under /p:WasmEnableThreads=true
    • ref assemblies should use FeatureWasmThreads in project files and FEATURE_WASM_THREADS in C# code to conditionally include [UnsupportedOSPlatform("browser")] guards around multi-threading APIs, and include the ref assembly in Microsoft.NET.WebAssembly.Threading
    • CoreLib uses FeatureWasmThreads and FEATURE_WASM_THREADS to define System.Thread.IsThreadStartSupported. All other code should check System.Thread.IsThreadStartSupported to throw a PNSE. There should not be [UnsupportedOSPlatform("browser")] guards in CoreLib
    • EventPipe and diagnostics should use FeatureWasmPerfTracing and FEATURE_WASM_PERFTRACING (and a constant?).
  • Add separate browser-mt and browser-mt-eventpipe samples.
  • Land the branch changes in main

In .NET 7 RC2

In .NET 8

...

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Apr 18, 2022
  2. removed
    untriagedNew issue has not been triaged by the area owner
    on Apr 18, 2022
  3. added this to the 7.0.0 milestone on Apr 18, 2022
  4. modified the milestones: 7.0.0, 8.0.0 on Aug 11, 2022
  5. TheXenocide commented on Sep 7, 2022

    @TheXenocide

    Ooh, just came to check in on how things were going on the mono wasm side of this and came across this tracking issue. Nice to see this being tracked on the dotnet/runtime side now. It's good to see that the browser-wasm RID was the final answer on that particular design challenge, but I remember how much discussion there was about trying to avoid adding additional runtimes unnecessarily. Trying to make sense of the current state of these tickets, are we expecting that the browser-wasm runtime will be multi-purpose and have some convention for choosing subtypes, rather than defining new RIDs for multi-threaded and perf-trace package variants? Part of me feels like the multi-thread variant would be better served by its own RID if there are plans to support both (fundamentally different) runtimes for any extended period (e.g. reference assemblies/contracts can expose different supported surface areas at compile time rather than throwing runtime exceptions).

    Is there a sense of how this will work for packaging and compile MSBuild conditions? It seems like WasmEnableThreads is rather narrow and probably only impacts the application build, not so much for libraries, NuGet packaging, etc. unless the desired result is for the compiler to be able to generate all variants automatically, but it seems like there would be significant design implications there, where performance and a variety of other factors would want to be able to provide different implementations for the different environments (e.g. concurrency-safe collection types could ignore concurrency without MT but might need to leverage platform-specific no-lock behaviors, etc.) Understandable if these aren't answered yet, just trying to get a sense of how these things intend to be differentiated by component developers between the runtime and consuming developers.

    I ask here mainly because it seems there are multiple possible threads that seem appropriate. Feel free to move this comment or direct me where best to move the discussion. Otherwise, glad to see there's already some experimental support running now.

  6. sajjadarashhh commented on Sep 19, 2022

    @sajjadarashhh

    what happend if this feature not support with browser?

  7. knight1219 commented on Oct 12, 2022

    @knight1219

    How, if any, effect for this have on Task based threading? If one creates multiple HttpClient.GetAsync tasks and schedules them using Task.WhenAll, will all tasks run in parallel on their own threads? Does each task need the ConfigureAwait(false) to be set?

    If that is the case and you are sharing this code between Blazor WASM and Blazor Hybrid, are there any repercussions in MAUI by doing that?

  8. kg commented on Oct 12, 2022

    @kg
    Contributor

    Threading allows tasks to run on multiple threads, yes. Things that interact with browser APIs like HTTP are a more complex scenario, because browser APIs have thread affinity (think the nightmare of COM apartments, but worse)

  9. baywet commented on Nov 7, 2022

    @baywet

    The Blazor needs to provide dotnet.worker.js as a js-module-threads asset list item probably needs its own issue for the following reasons:

    • to provide visibility to people (too me a while to find this post from the error message)
    • to clearly mention that blazor wasm apps won't be able to work currently without it
    • so it can be prioritized accordingly (lots of people on blazor wasm, they can't use the feature for the time being)

    The error message for visibility

    Assert failed: Can't find asset for js-module-threads
        at Us (dotnet.7.0.0-rc.2.22472.3.9fl1sjtbvn.js:5:45132)
        at Object.Zs [as allocateUnusedWorker] (dotnet.7.0.0-rc.2.22472.3.9fl1sjtbvn.js:5:52972)
        at Object.allocateUnusedWorker (dotnet.7.0.0-rc.2.22472.3.9fl1sjtbvn.js:5:41466)
        at rs (dotnet.7.0.0-rc.2.22472.3.9fl1sjtbvn.js:5:42820)
        at yu (dotnet.7.0.0-rc.2.22472.3.9fl1sjtbvn.js:5:106551)
        at async dotnet.7.0.0-rc.2.22472.3.9fl1sjtbvn.js:5:104732
    

    Trying to poke around by finding dotnet.worker.js and copying it with the right name doesn't seem to be any use as the referencing code really expects it to be part of the bundle.

  10. 12 remaining items

  11. pavelsavara commented on Nov 9, 2023

    @pavelsavara
    Member

    I updated MT tracking issue #85592

  12. tebeco commented on Jan 12, 2024

    @tebeco

    hello,

    Anyone know if this meta tracker could updated for net8 ? now that the release is done ?
    I've seen a question on the C# Discord server, search engine found this issue as the first search result, but I can't seems to tell what changed from net7 to net8 from this tracker

    image

  13. pavelsavara commented on Jan 29, 2024

    @pavelsavara
    Member

    Anyone know if this meta tracker could updated for net8 ?

    There were mostly low level steps toward multi-threading during Net8, but it's not supported in Net8.
    For the current progress on Net9, please have look at #85592

  14. tebeco commented on Jan 29, 2024

    @tebeco

    Anyone know if this meta tracker could updated for net8 ?

    There were mostly low level steps toward multi-threading during Net8, but it's not supported in Net8. For the current progress on Net9, please have look at #85592

    Ah cool, thx a lot for the next release tracker :)


    image

    This image is why I asked,
    It was usefully showing net7.0 - RC2
    and also showing net9.0 milestone, but is missing anything related net8.0 that being ultra small or bigger type of release

    Now i understand that there's another one regarding Net9.0

    The question is ... from an outsider point of you it would be nice to have this issue either

    • renamed to clarify it's only net7 (probably not the case)
    • closed if all done (probably not the case)
    • updated every release (ie: net8.0: list of PR)
    • list all possible tracker per release and each release issue summing it

    I'm not trying to be picky, I'm just hardly able to try to follow up cross release "Epic size" feature when there's a lot of cross over that are not listed.
    There's probably other ways i suppose but this ticket title seems like the perfect candidate to list the "per release"

  15. modified the milestones: 9.0.0, 10.0.0 on Jun 28, 2024
  16. modified the milestones: 10.0.0, Future on Feb 17, 2025
  17. sbeji-fab commented on Dec 16, 2025

    @sbeji-fab

    Are there any updates regarding this feature?
    Its been silent for long time

  18. OptimusPi commented on Mar 28, 2026

    @OptimusPi

    bump :(

  19. added
    disabled-testThe test is disabled in source code against the issue
    on Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

arch-wasmWebAssembly architecturearea-VM-threading-monodisabled-testThe test is disabled in source code against the issueos-browserBrowser variant of arch-wasmtrackingThis issue is tracking the completion of other related issues.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions