Skip to content

[dotnet watch] Make application of changes always async#52469

Merged
tmat merged 3 commits intodotnet:release/10.0.3xxfrom
tmat:AsyncApply
Jan 29, 2026
Merged

[dotnet watch] Make application of changes always async#52469
tmat merged 3 commits intodotnet:release/10.0.3xxfrom
tmat:AsyncApply

Conversation

@tmat
Copy link
Copy Markdown
Member

@tmat tmat commented Jan 14, 2026

Application of changes has two code paths. When the process is suspended at a breakpoint we can't wait until the changes are applied in the process because the agent in the process can't execute until the process is resumed by the debugger. In that case we queued an update, assume it's succeeded and continue. If the process isn't suspended, we wait until the agent finishes applying the changes.

This distinction requires debugger API that tell us whether or not the process is suspended. This API is currently only available in VS, not in VS Code.
Rather than adding the API to VS Code, it is simpler to avoid synchronous waiting for completion of the apply operation altogether.
All we need to do on the code path that applies changes is to hook up task completions at various stages that aggregate and report results when apply operations complete.

@mmitche mmitche deleted the branch dotnet:release/10.0.3xx January 17, 2026 00:38
@mmitche mmitche closed this Jan 17, 2026
@tmat tmat reopened this Jan 18, 2026
@tmat tmat marked this pull request as ready for review January 20, 2026 17:49
@tmat tmat requested review from a team as code owners January 20, 2026 17:49
@tmat tmat changed the title Async apply [dontet watch] Make application of changes always async Jan 20, 2026
@tmat tmat changed the title [dontet watch] Make application of changes always async [do not merge] [dontet watch] Make application of changes always async Jan 20, 2026
@tmat tmat changed the title [do not merge] [dontet watch] Make application of changes always async [dontet watch] Make application of changes always async Jan 20, 2026
@tmat tmat changed the base branch from release/10.0.2xx to release/10.0.3xx January 20, 2026 21:22
@tmat tmat changed the title [dontet watch] Make application of changes always async [dotnet watch] Make application of changes always async Jan 20, 2026
@tmat
Copy link
Copy Markdown
Member Author

tmat commented Jan 21, 2026

@DustinCampbell ptal

Comment thread src/BuiltInTools/HotReloadClient/HotReloadClient.cs
Comment thread src/BuiltInTools/HotReloadClient/HotReloadClient.cs Outdated
Comment thread src/BuiltInTools/HotReloadClient/HotReloadClient.cs Outdated
Comment thread src/BuiltInTools/Watch/HotReload/CompilationHandler.cs
Comment thread src/BuiltInTools/Watch/Process/RunningProject.cs Outdated
Copilot AI review requested due to automatic review settings January 29, 2026 00:33
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

This pull request refactors the hot reload change application mechanism to always be asynchronous, eliminating the distinction between suspended and non-suspended process states. Previously, the code had two paths: waiting synchronously for changes when the process wasn't suspended, or queueing updates asynchronously when it was suspended (at a breakpoint). This distinction required debugger APIs only available in Visual Studio. The new approach always queues updates asynchronously and reports results through fire-and-forget tasks that complete when operations finish.

Changes:

  • Replaced synchronous apply operations with async fire-and-forget pattern that reports completion via task continuations
  • Removed ApplyStatus enum and replaced return values with Task<Task<bool>> to support async completion tracking
  • Eliminated isProcessSuspended parameter from apply methods, simplifying the API
  • Updated message descriptors to reflect async timing (e.g., "C# and Razor changes applied in Xms" instead of per-project success messages)
  • Fixed process exit code handling for Unix signals (SIGKILL tracking)

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/BuiltInTools/HotReloadClient/ApplyStatus.cs Removed enum entirely as return type changed to bool
src/BuiltInTools/HotReloadClient/HotReloadClient.cs Changed apply methods to return Task<Task<bool>> and added QueueUpdateBatch helper
src/BuiltInTools/HotReloadClient/DefaultHotReloadClient.cs Refactored to use async queuing pattern with local completion tasks
src/BuiltInTools/HotReloadClient/Web/WebAssemblyHotReloadClient.cs Updated to use new async queuing pattern
src/BuiltInTools/HotReloadClient/HotReloadClients.cs Changed aggregation logic to work with async completion tasks
src/BuiltInTools/HotReloadClient/Utilities/ResponseFunc.cs Changed from Action to Func to return results
src/BuiltInTools/HotReloadClient/Web/BrowserConnection.cs Updated to return nullable response results
src/BuiltInTools/HotReloadClient/Web/AbstractBrowserRefreshServer.cs Added generic result type support
src/BuiltInTools/HotReloadClient/Logging/LogEvents.cs Updated log events for batch-based operations
src/BuiltInTools/Watch/HotReload/CompilationHandler.cs Implemented fire-and-forget pattern for apply operations with stopwatch timing
src/BuiltInTools/Watch/HotReload/HotReloadDotNetWatcher.cs Removed synchronous change handled logging, passes stopwatch to handlers
src/BuiltInTools/Watch/Process/RunningProject.cs Added CompleteApplyOperationAsync to wrap and handle apply task exceptions
src/BuiltInTools/Watch/Process/ProcessRunner.cs Enhanced signal tracking for Unix SIGKILL and Windows Ctrl+C
src/BuiltInTools/Watch/Context/EnvironmentOptions.cs Removed isHotReloadEnabled parameter from timeout method
src/BuiltInTools/dotnet-watch/Watch/StaticFileHandler.cs Added stopwatch for timing static asset changes
src/BuiltInTools/dotnet-watch/Program.cs Simplified process runner initialization
src/BuiltInTools/Watch.Aspire/DotNetWatchLauncher.cs Simplified process runner initialization
src/BuiltInTools/Watch/Microsoft.DotNet.HotReload.Watch.csproj Added reference to ResponseFunc utility
src/BuiltInTools/Watch/UI/IReporter.cs Updated message descriptors for async operations
test/dotnet-watch.Tests/TestUtilities/TestOptions.cs Changed timeout to nullable
test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs Updated tests to use new message descriptors
test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs Updated tests to use new message descriptors and removed per-project assertions
test/dotnet-watch.Tests/Browser/BrowserTests.cs Updated test to use new message descriptor
test/Microsoft.Extensions.DotNetDeltaApplier.Tests/HotReloadClientTests.cs Removed suspended/non-suspended test distinction, updated to await async completion
test/Microsoft.TemplateEngine.Cli.UnitTests/ParserTests/InstallTests.cs Removed trailing whitespace

Comment thread src/BuiltInTools/HotReloadClient/HotReloadClient.cs Outdated
Comment thread src/BuiltInTools/HotReloadClient/HotReloadClient.cs Outdated
Comment thread src/BuiltInTools/Watch/Process/ProcessRunner.cs Outdated
Comment thread src/BuiltInTools/Watch/HotReload/HotReloadDotNetWatcher.cs
@tmat tmat merged commit af70221 into dotnet:release/10.0.3xx Jan 29, 2026
26 checks passed
@tmat tmat deleted the AsyncApply branch January 29, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants