From 1f427919e68f82aa030dbc05de2067e4f64b79f7 Mon Sep 17 00:00:00 2001 From: Mbucari <37587114+Mbucari@users.noreply.github.com> Date: Sun, 2 Mar 2025 11:59:35 -0700 Subject: [PATCH] Try to solve threadding issues (#1168) --- Source/LibationAvalonia/ViewModels/MainVM.cs | 2 +- .../ViewModels/ProductsDisplayViewModel.cs | 12 +++++++++--- Source/LibationAvalonia/Views/MainWindow.axaml.cs | 8 +++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Source/LibationAvalonia/ViewModels/MainVM.cs b/Source/LibationAvalonia/ViewModels/MainVM.cs index 35089bb0..9e6a602c 100644 --- a/Source/LibationAvalonia/ViewModels/MainVM.cs +++ b/Source/LibationAvalonia/ViewModels/MainVM.cs @@ -41,7 +41,7 @@ namespace LibationAvalonia.ViewModels { await Task.WhenAll( SetBackupCountsAsync(fullLibrary), - ProductsDisplay.UpdateGridAsync(fullLibrary)); + Task.Run(() => ProductsDisplay.UpdateGridAsync(fullLibrary))); } private static string menufyText(string header) => Configuration.IsMacOs ? header : $"_{header}"; diff --git a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs index d8bfee95..47173b02 100644 --- a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs +++ b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs @@ -11,6 +11,7 @@ using ReactiveUI; using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -102,16 +103,17 @@ namespace LibationAvalonia.ViewModels internal async Task BindToGridAsync(List dbBooks) { - GridEntries = new(SOURCE) { Filter = CollectionFilter }; + var sc = await Dispatcher.UIThread.InvokeAsync(() => AvaloniaSynchronizationContext.Current); + AvaloniaSynchronizationContext.SetSynchronizationContext(sc); var geList = await LibraryBookEntry.GetAllProductsAsync(dbBooks); - var seriesEntries = await SeriesEntry.GetAllSeriesEntriesAsync(dbBooks); //Create the filtered-in list before adding entries to avoid a refresh FilteredInGridEntries = geList.Union(seriesEntries.SelectMany(s => s.Children)).FilterEntries(FilterString); //Adding entries to the Source list will invoke CollectionFilter - SOURCE.AddRange(geList.Concat(seriesEntries).OrderDescending(new RowComparer(null))); + //Perform on UI thread for safety + await Dispatcher.UIThread.InvokeAsync(() => SOURCE.AddRange(geList.Concat(seriesEntries).OrderDescending(new RowComparer(null)))); //Add all children beneath their parent foreach (var series in seriesEntries) @@ -121,6 +123,10 @@ namespace LibationAvalonia.ViewModels SOURCE.Insert(++seriesIndex, child); } + // Adding SOURCE to the DataGridViewCollection after building the source + //Saves ~500 ms on a library of ~4500 books. + //Perform on UI thread for safety + await Dispatcher.UIThread.InvokeAsync(() => GridEntries = new(SOURCE) { Filter = CollectionFilter }); GridEntries.CollectionChanged += GridEntries_CollectionChanged; GridEntries_CollectionChanged(); } diff --git a/Source/LibationAvalonia/Views/MainWindow.axaml.cs b/Source/LibationAvalonia/Views/MainWindow.axaml.cs index 005f3654..a70755dc 100644 --- a/Source/LibationAvalonia/Views/MainWindow.axaml.cs +++ b/Source/LibationAvalonia/Views/MainWindow.axaml.cs @@ -63,12 +63,14 @@ namespace LibationAvalonia.Views public async Task OnLibraryLoadedAsync(List initialLibrary) { + //Get the ViewModel before crossing the await boundary + var vm = ViewModel; if (QuickFilters.UseDefault) - await ViewModel.PerformFilter(QuickFilters.Filters.FirstOrDefault()); + await vm.PerformFilter(QuickFilters.Filters.FirstOrDefault()); await Task.WhenAll( - ViewModel.SetBackupCountsAsync(initialLibrary), - ViewModel.ProductsDisplay.BindToGridAsync(initialLibrary)); + vm.SetBackupCountsAsync(initialLibrary), + Task.Run(() => vm.ProductsDisplay.BindToGridAsync(initialLibrary))); } public void ProductsDisplay_LiberateClicked(object _, LibraryBook libraryBook) => ViewModel.LiberateClicked(libraryBook);