Skip to content

Commit ba448fa

Browse files
authored
Fix: Fixed issue where items were sometimes not displayed (#14581)
1 parent 1e8e437 commit ba448fa

File tree

1 file changed

+64
-46
lines changed

1 file changed

+64
-46
lines changed

src/Files.App/Data/Models/ItemViewModel.cs

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public sealed class ItemViewModel : ObservableObject, IDisposable
3030
{
3131
private readonly SemaphoreSlim enumFolderSemaphore;
3232
private readonly SemaphoreSlim getFileOrFolderSemaphore;
33+
private readonly SemaphoreSlim bulkOperationSemaphore;
3334
private readonly ConcurrentQueue<(uint Action, string FileName)> operationQueue;
3435
private readonly ConcurrentQueue<uint> gitChangesQueue;
3536
private readonly ConcurrentDictionary<string, bool> itemLoadQueue;
@@ -484,6 +485,7 @@ public ItemViewModel(LayoutPreferencesManager folderSettingsViewModel)
484485
gitChangedEvent = new AsyncManualResetEvent();
485486
enumFolderSemaphore = new SemaphoreSlim(1, 1);
486487
getFileOrFolderSemaphore = new SemaphoreSlim(50);
488+
bulkOperationSemaphore = new SemaphoreSlim(1, 1);
487489
dispatcherQueue = DispatcherQueue.GetForCurrentThread();
488490

489491
UserSettingsService.OnSettingChangedEvent += UserSettingsService_OnSettingChangedEvent;
@@ -687,41 +689,49 @@ void ClearDisplay()
687689
// Note that both DataGrid and GridView don't support multi-items changes notification, so here
688690
// we have to call BeginBulkOperation to suppress CollectionChanged and call EndBulkOperation
689691
// in the end to fire a CollectionChanged event with NotifyCollectionChangedAction.Reset
690-
FilesAndFolders.BeginBulkOperation();
691-
692-
// After calling BeginBulkOperation, ObservableCollection.CollectionChanged is suppressed
693-
// so modifies to FilesAndFolders won't trigger UI updates, hence below operations can be
694-
// run safely without needs of dispatching to UI thread
695-
void ApplyChanges()
692+
await bulkOperationSemaphore.WaitAsync(addFilesCTS.Token);
693+
try
696694
{
697-
if (addFilesCTS.IsCancellationRequested)
698-
return;
695+
FilesAndFolders.BeginBulkOperation();
699696

700-
FilesAndFolders.Clear();
701-
FilesAndFolders.AddRange(filesAndFoldersLocal);
697+
// After calling BeginBulkOperation, ObservableCollection.CollectionChanged is suppressed
698+
// so modifies to FilesAndFolders won't trigger UI updates, hence below operations can be
699+
// run safely without needs of dispatching to UI thread
700+
void ApplyChanges()
701+
{
702+
if (addFilesCTS.IsCancellationRequested)
703+
return;
702704

703-
if (folderSettings.DirectoryGroupOption != GroupOption.None)
704-
OrderGroups();
705-
}
705+
FilesAndFolders.Clear();
706+
FilesAndFolders.AddRange(filesAndFoldersLocal);
706707

707-
void UpdateUI()
708-
{
709-
// Trigger CollectionChanged with NotifyCollectionChangedAction.Reset
710-
// once loading is completed so that UI can be updated
711-
FilesAndFolders.EndBulkOperation();
712-
UpdateEmptyTextType();
713-
DirectoryInfoUpdated?.Invoke(this, EventArgs.Empty);
714-
}
708+
if (folderSettings.DirectoryGroupOption != GroupOption.None)
709+
OrderGroups();
710+
}
715711

716-
if (NativeWinApiHelper.IsHasThreadAccessPropertyPresent && dispatcherQueue.HasThreadAccess)
717-
{
718-
await Task.Run(ApplyChanges);
719-
UpdateUI();
712+
void UpdateUI()
713+
{
714+
// Trigger CollectionChanged with NotifyCollectionChangedAction.Reset
715+
// once loading is completed so that UI can be updated
716+
FilesAndFolders.EndBulkOperation();
717+
UpdateEmptyTextType();
718+
DirectoryInfoUpdated?.Invoke(this, EventArgs.Empty);
719+
}
720+
721+
if (NativeWinApiHelper.IsHasThreadAccessPropertyPresent && dispatcherQueue.HasThreadAccess)
722+
{
723+
await Task.Run(ApplyChanges);
724+
UpdateUI();
725+
}
726+
else
727+
{
728+
ApplyChanges();
729+
await dispatcherQueue.EnqueueOrInvokeAsync(UpdateUI);
730+
}
720731
}
721-
else
732+
finally
722733
{
723-
ApplyChanges();
724-
await dispatcherQueue.EnqueueOrInvokeAsync(UpdateUI);
734+
bulkOperationSemaphore.Release();
725735
}
726736
}
727737
catch (Exception ex)
@@ -820,30 +830,38 @@ public async Task GroupOptionsUpdatedAsync(CancellationToken token)
820830

821831
try
822832
{
823-
FilesAndFolders.BeginBulkOperation();
824-
UpdateGroupOptions();
825-
826-
if (FilesAndFolders.IsGrouped)
833+
await bulkOperationSemaphore.WaitAsync(token);
834+
try
827835
{
828-
await Task.Run(() =>
836+
FilesAndFolders.BeginBulkOperation();
837+
UpdateGroupOptions();
838+
839+
if (FilesAndFolders.IsGrouped)
829840
{
830-
FilesAndFolders.ResetGroups(token);
831-
if (token.IsCancellationRequested)
832-
return;
841+
await Task.Run(() =>
842+
{
843+
FilesAndFolders.ResetGroups(token);
844+
if (token.IsCancellationRequested)
845+
return;
833846

834-
OrderGroups();
835-
});
847+
OrderGroups();
848+
});
849+
}
850+
else
851+
{
852+
await OrderFilesAndFoldersAsync();
853+
}
854+
855+
if (token.IsCancellationRequested)
856+
return;
857+
858+
await dispatcherQueue.EnqueueOrInvokeAsync(
859+
FilesAndFolders.EndBulkOperation);
836860
}
837-
else
861+
finally
838862
{
839-
await OrderFilesAndFoldersAsync();
863+
bulkOperationSemaphore.Release();
840864
}
841-
842-
if (token.IsCancellationRequested)
843-
return;
844-
845-
await dispatcherQueue.EnqueueOrInvokeAsync(
846-
FilesAndFolders.EndBulkOperation);
847865
}
848866
catch (Exception ex)
849867
{

0 commit comments

Comments
 (0)