From 45b471c913572c6550e3596982052a776005afaa Mon Sep 17 00:00:00 2001 From: AmirMS <104940545+AmelBawa-msft@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:35:04 -0800 Subject: [PATCH] Prevent concurrent loading of catalogs (#2316) --- .../ViewModels/PackageCatalogListViewModel.cs | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs index dd8d13f067..c74496f30e 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Threading; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; @@ -17,16 +18,18 @@ namespace DevHome.SetupFlow.ViewModels; -public partial class PackageCatalogListViewModel : ObservableObject +public partial class PackageCatalogListViewModel : ObservableObject, IDisposable { private readonly ICatalogDataSourceLoader _catalogDataSourceLoader; private readonly IExtensionService _extensionService; private readonly PackageCatalogViewModelFactory _packageCatalogViewModelFactory; private readonly DispatcherQueue _dispatcher; + private readonly SemaphoreSlim _loadCatalogsSemaphore = new(1, 1); [ObservableProperty] [NotifyPropertyChangedFor(nameof(CatalogFullPath))] private PackageCatalogViewModel _viewAllCatalog; + private bool disposedValue; public List CatalogFullPath => new() { @@ -61,10 +64,12 @@ public PackageCatalogListViewModel( /// private async Task LoadCatalogsAsync() { - PackageCatalogs.Clear(); - AddShimmers(_catalogDataSourceLoader.CatalogCount); + // Prevent concurrent loading of catalogs + await _loadCatalogsSemaphore.WaitAsync(); try { + PackageCatalogs.Clear(); + AddShimmers(_catalogDataSourceLoader.CatalogCount); await foreach (var dataSourceCatalogs in _catalogDataSourceLoader.LoadCatalogsAsync()) { foreach (var catalog in dataSourceCatalogs) @@ -75,16 +80,20 @@ private async Task LoadCatalogsAsync() RemoveShimmers(dataSourceCatalogs.Count); } + + // Remove any remaining shimmers: + // This can happen if for example a catalog was detected but not + // displayed (e.g. catalog with no packages to display) + RemoveShimmers(PackageCatalogShimmers.Count); } catch (Exception e) { Log.Logger?.ReportError(Log.Component.AppManagement, $"Failed to load catalogs.", e); } - - // Remove any remaining shimmers: - // This can happen if for example a catalog was detected but not - // displayed (e.g. catalog with no packages to display) - RemoveShimmers(PackageCatalogShimmers.Count); + finally + { + _loadCatalogsSemaphore.Release(); + } } /// @@ -146,4 +155,23 @@ private async void OnExtensionChangedAsync(object sender, EventArgs e) { await _dispatcher.EnqueueAsync(() => LoadCatalogsAsync()); } + + private void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _loadCatalogsSemaphore.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } }