Skip to content

Commit

Permalink
Fix: Fixed issue where items were sometimes not displayed (#14581)
Browse files Browse the repository at this point in the history
  • Loading branch information
hishitetsu authored Jan 30, 2024
1 parent 1e8e437 commit ba448fa
Showing 1 changed file with 64 additions and 46 deletions.
110 changes: 64 additions & 46 deletions src/Files.App/Data/Models/ItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public sealed class ItemViewModel : ObservableObject, IDisposable
{
private readonly SemaphoreSlim enumFolderSemaphore;
private readonly SemaphoreSlim getFileOrFolderSemaphore;
private readonly SemaphoreSlim bulkOperationSemaphore;
private readonly ConcurrentQueue<(uint Action, string FileName)> operationQueue;
private readonly ConcurrentQueue<uint> gitChangesQueue;
private readonly ConcurrentDictionary<string, bool> itemLoadQueue;
Expand Down Expand Up @@ -484,6 +485,7 @@ public ItemViewModel(LayoutPreferencesManager folderSettingsViewModel)
gitChangedEvent = new AsyncManualResetEvent();
enumFolderSemaphore = new SemaphoreSlim(1, 1);
getFileOrFolderSemaphore = new SemaphoreSlim(50);
bulkOperationSemaphore = new SemaphoreSlim(1, 1);
dispatcherQueue = DispatcherQueue.GetForCurrentThread();

UserSettingsService.OnSettingChangedEvent += UserSettingsService_OnSettingChangedEvent;
Expand Down Expand Up @@ -687,41 +689,49 @@ void ClearDisplay()
// Note that both DataGrid and GridView don't support multi-items changes notification, so here
// we have to call BeginBulkOperation to suppress CollectionChanged and call EndBulkOperation
// in the end to fire a CollectionChanged event with NotifyCollectionChangedAction.Reset
FilesAndFolders.BeginBulkOperation();

// After calling BeginBulkOperation, ObservableCollection.CollectionChanged is suppressed
// so modifies to FilesAndFolders won't trigger UI updates, hence below operations can be
// run safely without needs of dispatching to UI thread
void ApplyChanges()
await bulkOperationSemaphore.WaitAsync(addFilesCTS.Token);
try
{
if (addFilesCTS.IsCancellationRequested)
return;
FilesAndFolders.BeginBulkOperation();

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

if (folderSettings.DirectoryGroupOption != GroupOption.None)
OrderGroups();
}
FilesAndFolders.Clear();
FilesAndFolders.AddRange(filesAndFoldersLocal);

void UpdateUI()
{
// Trigger CollectionChanged with NotifyCollectionChangedAction.Reset
// once loading is completed so that UI can be updated
FilesAndFolders.EndBulkOperation();
UpdateEmptyTextType();
DirectoryInfoUpdated?.Invoke(this, EventArgs.Empty);
}
if (folderSettings.DirectoryGroupOption != GroupOption.None)
OrderGroups();
}

if (NativeWinApiHelper.IsHasThreadAccessPropertyPresent && dispatcherQueue.HasThreadAccess)
{
await Task.Run(ApplyChanges);
UpdateUI();
void UpdateUI()
{
// Trigger CollectionChanged with NotifyCollectionChangedAction.Reset
// once loading is completed so that UI can be updated
FilesAndFolders.EndBulkOperation();
UpdateEmptyTextType();
DirectoryInfoUpdated?.Invoke(this, EventArgs.Empty);
}

if (NativeWinApiHelper.IsHasThreadAccessPropertyPresent && dispatcherQueue.HasThreadAccess)
{
await Task.Run(ApplyChanges);
UpdateUI();
}
else
{
ApplyChanges();
await dispatcherQueue.EnqueueOrInvokeAsync(UpdateUI);
}
}
else
finally
{
ApplyChanges();
await dispatcherQueue.EnqueueOrInvokeAsync(UpdateUI);
bulkOperationSemaphore.Release();
}
}
catch (Exception ex)
Expand Down Expand Up @@ -820,30 +830,38 @@ public async Task GroupOptionsUpdatedAsync(CancellationToken token)

try
{
FilesAndFolders.BeginBulkOperation();
UpdateGroupOptions();

if (FilesAndFolders.IsGrouped)
await bulkOperationSemaphore.WaitAsync(token);
try
{
await Task.Run(() =>
FilesAndFolders.BeginBulkOperation();
UpdateGroupOptions();

if (FilesAndFolders.IsGrouped)
{
FilesAndFolders.ResetGroups(token);
if (token.IsCancellationRequested)
return;
await Task.Run(() =>
{
FilesAndFolders.ResetGroups(token);
if (token.IsCancellationRequested)
return;

OrderGroups();
});
OrderGroups();
});
}
else
{
await OrderFilesAndFoldersAsync();
}

if (token.IsCancellationRequested)
return;

await dispatcherQueue.EnqueueOrInvokeAsync(
FilesAndFolders.EndBulkOperation);
}
else
finally
{
await OrderFilesAndFoldersAsync();
bulkOperationSemaphore.Release();
}

if (token.IsCancellationRequested)
return;

await dispatcherQueue.EnqueueOrInvokeAsync(
FilesAndFolders.EndBulkOperation);
}
catch (Exception ex)
{
Expand Down

0 comments on commit ba448fa

Please sign in to comment.