From a5e739778a4a95480ff4b28718b45d905d1270cc Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 15 Jul 2025 08:03:43 -0700 Subject: [PATCH 1/2] Refactor async task handling to use WaitAsync for cancellation support - This makes sure that blocking calls still yield in a timely manner --- src/Aspire.Hosting/Dcp/DcpExecutor.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Aspire.Hosting/Dcp/DcpExecutor.cs b/src/Aspire.Hosting/Dcp/DcpExecutor.cs index 425bd739a05..06fefaf4a5a 100644 --- a/src/Aspire.Hosting/Dcp/DcpExecutor.cs +++ b/src/Aspire.Hosting/Dcp/DcpExecutor.cs @@ -789,7 +789,7 @@ private async Task CreateContainersAndExecutablesAsync(CancellationToken cancell var containersTask = CreateContainersAsync(toCreate.Where(ar => ar.DcpResource is Container), cancellationToken); var executablesTask = CreateExecutablesAsync(toCreate.Where(ar => ar.DcpResource is Executable), cancellationToken); - await Task.WhenAll(containersTask, executablesTask).ConfigureAwait(false); + await Task.WhenAll(containersTask, executablesTask).WaitAsync(cancellationToken).ConfigureAwait(false); } private void AddAllocatedEndpointInfo(IEnumerable resources) @@ -1084,10 +1084,10 @@ async Task CreateResourceExecutablesAsyncCore(IResource resource, IEnumerable(); foreach (var group in executableResources.GroupBy(e => e.ModelResource)) { - tasks.Add(CreateResourceExecutablesAsyncCore(group.Key, group, cancellationToken)); + tasks.Add(Task.Run(() => CreateResourceExecutablesAsyncCore(group.Key, group, cancellationToken), cancellationToken)); } - return Task.WhenAll(tasks); + return Task.WhenAll(tasks).WaitAsync(cancellationToken); } finally { @@ -1097,9 +1097,6 @@ async Task CreateResourceExecutablesAsyncCore(IResource resource, IEnumerable CreateContainerAsyncCore(cr, cancellationToken), cancellationToken)); } - await Task.WhenAll(tasks).ConfigureAwait(false); + await Task.WhenAll(tasks).WaitAsync(cancellationToken).ConfigureAwait(false); } finally { @@ -1351,9 +1348,6 @@ async Task CreateContainerAsyncCore(AppResource cr, CancellationToken cancellati private async Task CreateContainerAsync(AppResource cr, ILogger resourceLogger, CancellationToken cancellationToken) { - // Force async execution - await Task.Yield(); - await _executorEvents.PublishAsync(new OnResourceStartingContext(cancellationToken, KnownResourceTypes.Container, cr.ModelResource, cr.DcpResource.Metadata.Name)).ConfigureAwait(false); var dcpContainerResource = (Container)cr.DcpResource; From c59722aa43dba108884c2850eec4a9144cb31912 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 15 Jul 2025 12:14:34 -0700 Subject: [PATCH 2/2] Ensure asynchronous execution for resource and container creation to prevent blocking --- src/Aspire.Hosting/Dcp/DcpExecutor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Aspire.Hosting/Dcp/DcpExecutor.cs b/src/Aspire.Hosting/Dcp/DcpExecutor.cs index 06fefaf4a5a..02497a8796c 100644 --- a/src/Aspire.Hosting/Dcp/DcpExecutor.cs +++ b/src/Aspire.Hosting/Dcp/DcpExecutor.cs @@ -1084,6 +1084,7 @@ async Task CreateResourceExecutablesAsyncCore(IResource resource, IEnumerable(); foreach (var group in executableResources.GroupBy(e => e.ModelResource)) { + // Force this to be async so that blocking code does not stop other executables from being created. tasks.Add(Task.Run(() => CreateResourceExecutablesAsyncCore(group.Key, group, cancellationToken), cancellationToken)); } @@ -1335,6 +1336,7 @@ async Task CreateContainerAsyncCore(AppResource cr, CancellationToken cancellati } } + // Force this to be async so that blocking code does not stop other containers from being created. tasks.Add(Task.Run(() => CreateContainerAsyncCore(cr, cancellationToken), cancellationToken)); }