Skip to content

WasmEnableThreads incrementalism is broken #98502

Description

@SteveSandersonMS

Description

If you have a Blazor WebAssembly app with WasmEnableThreads=true, and then change it to false, the build output is corrupted and won't work until you delete bin/obj and build again.

Reproduction Steps

  1. Create a .NET 9 Blazor WebAssembly app with WasmEnableThreads=true. Make sure you set this flag before you build for the first time.
  2. Run it from VS with Ctrl+F5 and observe it working
  3. Change WasmEnableThreads to false
  4. Ctrl+F5 again

Expected behavior

It should work in single-threaded mode

Actual behavior

It fails with:

image

Regression?

No

Known Workarounds

Delete bin & obj folders

(which unfortunately is not something we can expect developers to do in reality)

Configuration

.NET 9 WebAssembly

Other information

No response

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Feb 15, 2024
  2. SteveSandersonMS commented on Feb 15, 2024

    @SteveSandersonMS
    MemberAuthor
  3. SteveSandersonMS commented on Feb 15, 2024

    @SteveSandersonMS
    MemberAuthor

    Note that a similar problem also happens when switching WasmEnableThreads from false to true without deleting bin/obj, which is even more confusing because then you will likely think that further config is required to enable threading, when it isn't.

  4. added this to the 9.0.0 milestone on Feb 15, 2024
  5. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on Feb 15, 2024
  6. lewing commented on Feb 16, 2024

    @lewing
    Member

    Thanks for pointing this out, we'll make sure it gets resolved

  7. maraf commented on Feb 17, 2024

    @maraf
    Member

    The problem is with conversion to webcil format. The ConvertDllsToWebCil compares only file timestamp, but not if the original location has changed

    if (Utils.IsNewerThan(dllFilePath, finalWebcil))

  8. ghost added
    in-prThere is an active PR which will close this issue when it is merged
    on Feb 17, 2024
  9. removed
    in-prThere is an active PR which will close this issue when it is merged
    on Jun 3, 2024
  10. modified the milestones: 9.0.0, 10.0.0 on Jul 30, 2024
  11. modified the milestones: 10.0.0, Future on Dec 12, 2024
  12. waliarubal commented on Jan 16, 2025

    @waliarubal

    This issue is impacting my application running on Avalonia 11 and .NET 9. As soon as I set this flag 'true', the app stops loading altogether in browser. Any ETA on when this issue will be resolved?

  13. idg10 commented on Jun 3, 2025

    @idg10
    Contributor

    @waliarubal

    This issue is impacting my application running on Avalonia 11 and .NET 9. As soon as I set this flag 'true', the app stops loading altogether in browser. Any ETA on when this issue will be resolved?

    You might be running into a different issue. Is it possible tht you're using the embedded 'devserver'? (This is used by, amongst other things, standalone Blazor WebAssembly apps. It provides a web server that hosts wasm-based apps. I don't know if browser-based Avalonia apps use it but if they're using WebAssembly, it would make sense for them to use this same devserver that Blazor uses.)

    In .NET 9.0, when you enable WasmEnableThreads, the app fails to load due to a CORS issue in WebAssembly devserver. Basically, the browser tries to download a file that will have a name something like https://localhost:7209/_framework/dotnet.native.worker.1t59g4t9vs.mjs, and when the devserver reponds to that request, it does not set the necessary Cross-Origin-Embedder-Policy header. If you open the browser dev tools, go to the console page, then look at the Issues section you may see it reporting this problem.

    This was actually fixed back in October 2024: dotnet/aspnetcore#58287

    However, that fix is for the .NET 10.0 branch. That change has not been backported to the NET 9.0 branch. You can see the line of code that fixes the problem here:

    https://github.com/dotnet/aspnetcore/blob/aa0ae536e89b8b8e2c2ecb1cb336451cf45387e5/src/Components/WebAssembly/DevServer/src/Server/Startup.cs#L46

    but the release/9.0 branch currently (2025/06/03) has this for that line:

    https://github.com/dotnet/aspnetcore/blob/90dc083aadee6fc611cc00b1424f007f19eabcce/src/Components/WebAssembly/DevServer/src/Server/Startup.cs#L46

    Note that on the .NET 9.0 branch (today) it does not look for the .mjs extension in the path. And that's why Blazor WebAssembly apps simply don't run at all in .NET 9.0 if you set this flag.

    The confusing thing is that .NET 9.0 did ship with some code in Blazor that knows about WASM threading. (It does set the right headers on some files. And it sets these headers specifically to enable multithreading: they are necessary to enable shared memory use, which is required for multithreading to work.) This initially gave me the impression that this is supposed to work. (When you try to enable threading, it changes its behaviour and you don't get any errors telling you that you're not supposed to do this.)

    Nonetheless, as far as I can tell, use of WasmEnableThreads in Blazor apps is not in fact supported in .NET 9.0. So If you want to use this setting, I think you have to use .NET 10.0 preview (or wait until .NET 10.0 ships).

    So although in theory they could backport that one line change to the .NET 9.0 branch, I'm not sure it would help: I suspect it's just one of many changes that are required for multithreading to work in .NET on WASM in the browser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions