diff --git a/src/Components/Components/src/Rendering/Renderer.cs b/src/Components/Components/src/Rendering/Renderer.cs index 63bc74062e..25512141d3 100644 --- a/src/Components/Components/src/Rendering/Renderer.cs +++ b/src/Components/Components/src/Rendering/Renderer.cs @@ -455,10 +455,7 @@ namespace Microsoft.AspNetCore.Components.Rendering } finally { - // RemoveEventHandlerIdsAsync is designed to be fired-and-forgotten - // It will clone and persist any state it needs if it needs to run asynchronously - _ = RemoveEventHandlerIdsAsync(_batchBuilder.DisposedEventHandlerIds.ToRange(), updateDisplayTask); - + RemoveEventHandlerIds(_batchBuilder.DisposedEventHandlerIds.ToRange(), updateDisplayTask); _batchBuilder.ClearStateForCurrentBatch(); _isBatchInProgress = false; } @@ -602,7 +599,7 @@ namespace Microsoft.AspNetCore.Components.Rendering } } - private async Task RemoveEventHandlerIdsAsync(ArrayRange eventHandlerIds, Task afterTaskIgnoreErrors) + private void RemoveEventHandlerIds(ArrayRange eventHandlerIds, Task afterTaskIgnoreErrors) { if (eventHandlerIds.Count == 0) { @@ -619,6 +616,13 @@ namespace Microsoft.AspNetCore.Components.Rendering } } else + { + _ = ContinueAfterTask(eventHandlerIds, afterTaskIgnoreErrors); + } + + // Factor out the async part into a separate local method purely so, in the + // synchronous case, there's no state machine or task construction + async Task ContinueAfterTask(ArrayRange eventHandlerIds, Task afterTaskIgnoreErrors) { // We need to delay the actual removal (e.g., until we've confirmed the client // has processed the batch and hence can be sure not to reuse the handler IDs @@ -636,8 +640,8 @@ namespace Microsoft.AspNetCore.Components.Rendering // That remains the caller's business. } - // We know the next execution will complete synchronously, so nothing to await - _ = RemoveEventHandlerIdsAsync(eventHandlerIdsClone, Task.CompletedTask); + // We know the next execution will complete synchronously, so no infinite loop + RemoveEventHandlerIds(eventHandlerIdsClone, Task.CompletedTask); } }