diff --git a/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs b/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs index 58a7ac8d656f..992bd4fe498d 100644 --- a/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs +++ b/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs @@ -28,6 +28,7 @@ internal class RazorComponentEndpointDataSource<[DynamicallyAccessedMembers(Comp private List? _endpoints; private CancellationTokenSource _cancellationTokenSource; private IChangeToken _changeToken; + private IDisposable? _disposable; // THREADING: protected by _lock // Internal for testing. internal ComponentApplicationBuilder Builder => _builder; @@ -45,6 +46,7 @@ public RazorComponentEndpointDataSource( _renderModeEndpointProviders = renderModeEndpointProviders.ToArray(); _factory = factory; _hotReloadService = hotReloadService; + HotReloadService.ClearCacheEvent += OnHotReloadClearCache; DefaultBuilder = new RazorComponentsEndpointConventionBuilder( _lock, builder, @@ -139,12 +141,23 @@ private void UpdateEndpoints() _cancellationTokenSource = new CancellationTokenSource(); _changeToken = new CancellationChangeToken(_cancellationTokenSource.Token); oldCancellationTokenSource?.Cancel(); + oldCancellationTokenSource?.Dispose(); if (_hotReloadService is { MetadataUpdateSupported : true }) { - ChangeToken.OnChange(_hotReloadService.GetChangeToken, UpdateEndpoints); + _disposable?.Dispose(); + _disposable = ChangeToken.OnChange(_hotReloadService.GetChangeToken, UpdateEndpoints); } } } + + public void OnHotReloadClearCache(Type[]? types) + { + lock (_lock) + { + _disposable?.Dispose(); + _disposable = null; + } + } public override IChangeToken GetChangeToken() { diff --git a/src/Components/Endpoints/src/DependencyInjection/HotReloadService.cs b/src/Components/Endpoints/src/DependencyInjection/HotReloadService.cs index 51680ca61034..ad3c985b564f 100644 --- a/src/Components/Endpoints/src/DependencyInjection/HotReloadService.cs +++ b/src/Components/Endpoints/src/DependencyInjection/HotReloadService.cs @@ -18,6 +18,7 @@ public HotReloadService() private CancellationTokenSource _tokenSource = new(); private static event Action? UpdateApplicationEvent; + internal static event Action? ClearCacheEvent; public bool MetadataUpdateSupported { get; internal set; } @@ -27,11 +28,17 @@ public static void UpdateApplication(Type[]? changedTypes) { UpdateApplicationEvent?.Invoke(changedTypes); } + + public static void ClearCache(Type[]? types) + { + ClearCacheEvent?.Invoke(types); + } private void NotifyUpdateApplication(Type[]? changedTypes) { var current = Interlocked.Exchange(ref _tokenSource, new CancellationTokenSource()); current.Cancel(); + current.Dispose(); } public void Dispose()