Skip to content

Conversation

davidfowl
Copy link
Member

Description

If there's a blocking API call in the creation of the service it will block ctrl + c. This is because we assume that the cancellation token will be respected but that is not the case with these blocking APIs. This changes the logic so that WhenAll will yield if the token is fired.

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • No
  • Did you add public API?
    • No
  • Does the change make any security assumptions or guarantees?
    • No
  • Does the change require an update in our Aspire docs?
    • No

- This makes sure that blocking calls still yield in a timely manner
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jul 15, 2025
Copy link
Contributor

@Copilot 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 PR refactors DcpExecutor to make long-running Task.WhenAll calls cancellable by using WaitAsync and by offloading creation loops to Task.Run. It also removes redundant Task.Yield calls.

  • Changed Task.WhenAll(...).ConfigureAwait(false) to .WaitAsync(cancellationToken).ConfigureAwait(false) to respect cancellation.
  • Wrapped calls to CreateResourceExecutablesAsyncCore and CreateContainerAsyncCore in Task.Run with the cancellation token.
  • Removed await Task.Yield() as it’s no longer needed.
Comments suppressed due to low confidence (1)

src/Aspire.Hosting/Dcp/DcpExecutor.cs:792

  • [nitpick] No unit tests were added to verify cancellation behavior. Consider adding tests that trigger cancellation during WaitAsync to ensure tasks are cancelled as expected.
        await Task.WhenAll(containersTask, executablesTask).WaitAsync(cancellationToken).ConfigureAwait(false);

}

return Task.WhenAll(tasks);
return Task.WhenAll(tasks).WaitAsync(cancellationToken);
Copy link

Copilot AI Jul 15, 2025

Choose a reason for hiding this comment

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

This method is declared to return Task but returns a ValueTask from WaitAsync. You should await the WaitAsync inside the async method (with .ConfigureAwait(false)) instead of returning it directly.

Suggested change
return Task.WhenAll(tasks).WaitAsync(cancellationToken);
return await Task.WhenAll(tasks).WaitAsync(cancellationToken).ConfigureAwait(false);

Copilot uses AI. Check for mistakes.

Copy link
Member

@karolz-ms karolz-ms left a comment

Choose a reason for hiding this comment

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

Looks great

@davidfowl davidfowl merged commit a34cc7a into main Jul 15, 2025
276 checks passed
@davidfowl davidfowl deleted the davidfowl/cancel-whenall branch July 15, 2025 20:14
@davidfowl
Copy link
Member Author

/backport to release/9.4

Copy link
Contributor

Started backporting to release/9.4: https://github.com/dotnet/aspire/actions/runs/16303360659

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

Labels

needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants