Skip to content

Fix WebWorker hang when debugging Blazor WASM apps in Visual Studio#125617

Merged
ilonatommy merged 2 commits into
dotnet:mainfrom
ilonatommy:fix-debugging-webworker
Mar 19, 2026
Merged

Fix WebWorker hang when debugging Blazor WASM apps in Visual Studio#125617
ilonatommy merged 2 commits into
dotnet:mainfrom
ilonatommy:fix-debugging-webworker

Conversation

@ilonatommy
Copy link
Copy Markdown
Member

@ilonatommy ilonatommy commented Mar 16, 2026

Summary

When debugging a Blazor WebAssembly app that uses Web Workers (via the dotnet new webworker template, see dotnet/aspnetcore#65037) in Visual Studio, the worker thread hangs indefinitely during startup. The app never completes initialization and the worker appears stuck at importing worker's module.

await using var module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./_content/WorkerLib/dotnet-web-worker-client.js");

This PR fixes two issues in the BrowserDebugProxy (MonoProxy) that together cause the hang.

You can use this app to see the problem: BlazorAppRepro.zip

Root Cause

Issue 1 — Worker never resumed after Chrome pauses it on attach:

When VS sends Target.setAutoAttach({ waitForDebuggerOnStart: true }), Chrome pauses all new worker threads until the debugger explicitly sends Runtime.runIfWaitingForDebugger. The proxy's Target.attachedToTarget handler for workers only called CreateWorkerExecutionContext() but never sent Runtime.runIfWaitingForDebugger, leaving the worker frozen before any JS executed.

Issue 2 — Debugger.paused event forwarded to IDE instead of being resumed:

Even after resuming the worker, VS's JavaScript debugger auto-attaches with breakOnLoad: true, which fires a Debugger.paused event on the worker session. In OnDebuggerPaused's default case, when JustMyCode is enabled and the execution context isn't runtime-ready (IsRuntimeReady == false), the handler returns false — forwarding the pause to VS. VS's JS debugger receives the pause but doesn't resume it, leaving the worker stuck. Shortly after, the CDP connection crashes with ObjectDisposedException.

Changes

MonoProxy.cs — two targeted fixes:

  1. Target.attachedToTarget handler: For worker targets, send Runtime.runIfWaitingForDebugger after creating the worker execution context. This tells Chrome to unpause the worker thread.

  2. OnDebuggerPaused default case: When the session belongs to a worker (detected via context.ParentContext != null) and the runtime isn't ready yet, call SendResume instead of returning false. This prevents the pause from being forwarded to the IDE and lets the worker continue booting its WASM runtime.

Testing

Manually verified with a Blazor WASM Standalone app + webworker library project in VS 2022 (by replacing the .dlls VS uses):

  • Before fix: F5 → worker hangs at startup, app stuck at "Creating worker..."
  • After fix: F5 → worker runs to completion, app shows correct results, main-thread breakpoints (e.g., in Home.razor) hit correctly

Known Limitation

Breakpoints in C# code running inside the Web Worker (e.g., [JSExport] methods in the worker library) do not get hit. The debug proxy currently only attaches its SDB agent to the main page's WASM runtime, not the worker's second runtime. This is a pre-existing architectural limitation and is out of scope for this PR but I would like to have it solved as well. Any ideas on how to do it are welcome.

Contributes to dotnet/aspnetcore#65823.

@ilonatommy ilonatommy added this to the 11.0.0 milestone Mar 16, 2026
@ilonatommy ilonatommy self-assigned this Mar 16, 2026
@ilonatommy ilonatommy requested a review from thaystg as a code owner March 16, 2026 15:08
Copilot AI review requested due to automatic review settings March 16, 2026 15:08
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @thaystg, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a Visual Studio debugging hang for Blazor WebAssembly apps that use Web Workers by ensuring worker targets are resumed correctly when Chrome/VS pause them during attach/startup, preventing the worker from getting stuck before executing its module import.

Changes:

  • On Target.attachedToTarget for worker, send Runtime.runIfWaitingForDebugger after creating the worker execution context.
  • In OnDebuggerPaused (default case), when JustMyCode is enabled and a worker session isn’t runtime-ready yet, resume the worker instead of forwarding the pause to the IDE.

You can also share your feedback on Copilot code review. Take the survey.

The cobaltSveMicro job added in dotnet/performance#5127 targets
linux_arm64 on perfcobalt, which generates a dependency on the
build_linux_arm64_release_coreclr job. This job was never created
because linux_arm64 was not enabled in perf-build-jobs.yml, causing
all dotnet-runtime-perf pipeline builds to fail with a YAML
validation error since March 18.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ilonatommy ilonatommy closed this Mar 18, 2026
@ilonatommy ilonatommy deleted the fix-debugging-webworker branch March 18, 2026 09:10
@ilonatommy ilonatommy restored the fix-debugging-webworker branch March 18, 2026 10:37
@ilonatommy ilonatommy reopened this Mar 18, 2026
@ilonatommy ilonatommy merged commit 876f7e8 into dotnet:main Mar 19, 2026
45 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants