Skip to content

Commit bd3ffb1

Browse files
authored
Improve UI responsiveness while enumerating (#5991)
1 parent 2f7c349 commit bd3ffb1

File tree

2 files changed

+46
-100
lines changed

2 files changed

+46
-100
lines changed

Files/Filesystem/StorageEnumerators/UniversalStorageEnumerator.cs

+6-67
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Files.Filesystem.StorageItems;
44
using Files.Helpers;
55
using Files.Views.LayoutModes;
6+
using Microsoft.Toolkit.Uwp;
67
using System;
78
using System.Collections.Generic;
89
using System.Diagnostics;
@@ -11,8 +12,6 @@
1112
using System.Threading;
1213
using System.Threading.Tasks;
1314
using Windows.Storage;
14-
using Windows.Storage.FileProperties;
15-
using Windows.UI.Xaml.Media.Imaging;
1615

1716
namespace Files.Filesystem.StorageEnumerators
1817
{
@@ -79,7 +78,7 @@ ex is UnauthorizedAccessException
7978
}
8079
else
8180
{
82-
var fileEntry = await AddFileAsync(item.AsBaseStorageFile(), currentStorageFolder, returnformat, true, sourcePageType, cancellationToken);
81+
var fileEntry = await AddFileAsync(item.AsBaseStorageFile(), currentStorageFolder, returnformat, cancellationToken);
8382
if (fileEntry != null)
8483
{
8584
tempList.Add(fileEntry);
@@ -168,8 +167,6 @@ private static async Task<ListedItem> AddFileAsync(
168167
BaseStorageFile file,
169168
StorageFolderWithPath currentStorageFolder,
170169
string dateReturnFormat,
171-
bool suppressThumbnailLoading,
172-
Type sourcePageType,
173170
CancellationToken cancellationToken
174171
)
175172
{
@@ -185,67 +182,9 @@ CancellationToken cancellationToken
185182
var itemType = file.DisplayType;
186183
var itemFolderImgVis = false;
187184
var itemFileExtension = file.FileType;
185+
var itemEmptyImgVis = true;
186+
var itemThumbnailImgVis = false;
188187

189-
BitmapImage icon = new BitmapImage();
190-
byte[] iconData = null;
191-
bool itemThumbnailImgVis;
192-
bool itemEmptyImgVis;
193-
194-
if (sourcePageType != typeof(GridViewBrowser))
195-
{
196-
try
197-
{
198-
using var itemThumbnailImg = suppressThumbnailLoading ? null :
199-
await file.GetThumbnailAsync(ThumbnailMode.ListView, 40, ThumbnailOptions.UseCurrentScale);
200-
if (itemThumbnailImg != null)
201-
{
202-
itemEmptyImgVis = false;
203-
itemThumbnailImgVis = true;
204-
icon.DecodePixelWidth = 40;
205-
icon.DecodePixelHeight = 40;
206-
await icon.SetSourceAsync(itemThumbnailImg);
207-
iconData = await itemThumbnailImg.ToByteArrayAsync();
208-
}
209-
else
210-
{
211-
itemEmptyImgVis = true;
212-
itemThumbnailImgVis = false;
213-
}
214-
}
215-
catch
216-
{
217-
itemEmptyImgVis = true;
218-
itemThumbnailImgVis = false;
219-
// Catch here to avoid crash
220-
}
221-
}
222-
else
223-
{
224-
try
225-
{
226-
using var itemThumbnailImg = suppressThumbnailLoading ? null :
227-
await file.GetThumbnailAsync(ThumbnailMode.ListView, 80, ThumbnailOptions.UseCurrentScale);
228-
if (itemThumbnailImg != null)
229-
{
230-
itemEmptyImgVis = false;
231-
itemThumbnailImgVis = true;
232-
icon.DecodePixelWidth = 80;
233-
icon.DecodePixelHeight = 80;
234-
await icon.SetSourceAsync(itemThumbnailImg);
235-
iconData = await itemThumbnailImg.ToByteArrayAsync();
236-
}
237-
else
238-
{
239-
itemEmptyImgVis = true;
240-
itemThumbnailImgVis = false;
241-
}
242-
}
243-
catch
244-
{
245-
itemEmptyImgVis = true;
246-
itemThumbnailImgVis = false;
247-
}
248-
}
249188
if (cancellationToken.IsCancellationRequested)
250189
{
251190
return null;
@@ -274,8 +213,8 @@ CancellationToken cancellationToken
274213
IsHiddenItem = false,
275214
Opacity = 1,
276215
LoadUnknownTypeGlyph = itemEmptyImgVis,
277-
FileImage = icon,
278-
CustomIconData = iconData,
216+
FileImage = null,
217+
CustomIconData = null,
279218
LoadFileIcon = itemThumbnailImgVis,
280219
LoadFolderGlyph = itemFolderImgVis,
281220
ItemName = itemName,

Files/ViewModels/ItemViewModel.cs

+40-33
Original file line numberDiff line numberDiff line change
@@ -489,19 +489,19 @@ public async Task ApplyFilesAndFoldersChangesAsync()
489489
{
490490
if (filesAndFolders == null || filesAndFolders.Count == 0)
491491
{
492-
Action action = () =>
492+
void ClearDisplay()
493493
{
494494
FilesAndFolders.Clear();
495495
UpdateEmptyTextType();
496496
DirectoryInfoUpdated?.Invoke(this, EventArgs.Empty);
497-
};
497+
}
498498
if (CoreApplication.MainView.DispatcherQueue.HasThreadAccess)
499499
{
500-
action();
500+
ClearDisplay();
501501
}
502502
else
503503
{
504-
await CoreApplication.MainView.DispatcherQueue.EnqueueAsync(action);
504+
await CoreApplication.MainView.DispatcherQueue.EnqueueAsync(ClearDisplay);
505505
}
506506
return;
507507
}
@@ -517,7 +517,7 @@ public async Task ApplyFilesAndFoldersChangesAsync()
517517
// After calling BeginBulkOperation, ObservableCollection.CollectionChanged is suppressed
518518
// so modifies to FilesAndFolders won't trigger UI updates, hence below operations can be
519519
// run safely without needs of dispatching to UI thread
520-
Action applyChangesAction = () =>
520+
void ApplyChanges()
521521
{
522522
var startIndex = -1;
523523
var tempList = new List<ListedItem>();
@@ -572,26 +572,26 @@ void ApplyBulkInsertEntries()
572572
{
573573
OrderGroups();
574574
}
575-
};
575+
}
576576

577-
Action updateUIAction = () =>
577+
void UpdateUI()
578578
{
579579
// trigger CollectionChanged with NotifyCollectionChangedAction.Reset
580580
// once loading is completed so that UI can be updated
581581
FilesAndFolders.EndBulkOperation();
582582
UpdateEmptyTextType();
583583
DirectoryInfoUpdated?.Invoke(this, EventArgs.Empty);
584-
};
584+
}
585585

586586
if (CoreApplication.MainView.DispatcherQueue.HasThreadAccess)
587587
{
588-
await Task.Run(applyChangesAction);
589-
updateUIAction();
588+
await Task.Run(ApplyChanges);
589+
UpdateUI();
590590
}
591591
else
592592
{
593-
applyChangesAction();
594-
await CoreApplication.MainView.DispatcherQueue.EnqueueAsync(updateUIAction);
593+
ApplyChanges();
594+
await CoreApplication.MainView.DispatcherQueue.EnqueueAsync(UpdateUI);
595595
}
596596
}
597597
catch (Exception ex)
@@ -608,23 +608,23 @@ private Task OrderFilesAndFoldersAsync()
608608
return Task.CompletedTask;
609609
}
610610

611-
Action action = () =>
611+
void OrderEntries()
612612
{
613613
if (filesAndFolders.Count == 0)
614614
{
615615
return;
616616
}
617617

618618
filesAndFolders = SortingHelper.OrderFileList(filesAndFolders, folderSettings.DirectorySortOption, folderSettings.DirectorySortDirection).ToList();
619-
};
619+
}
620620

621621
if (CoreApplication.MainView.DispatcherQueue.HasThreadAccess)
622622
{
623-
return Task.Run(action);
623+
return Task.Run(OrderEntries);
624624
}
625625
else
626626
{
627-
action();
627+
OrderEntries();
628628
return Task.CompletedTask;
629629
}
630630
}
@@ -1584,16 +1584,20 @@ await DialogDisplayHelper.ShowDialogAsync(
15841584
}
15851585
else
15861586
{
1587-
List<ListedItem> fileList = await Win32StorageEnumerator.ListEntries(path, returnformat, hFile, findData, Connection, cancellationToken, -1, intermediateAction: async (intermediateList) =>
1587+
await Task.Run(async () =>
15881588
{
1589-
filesAndFolders.AddRange(intermediateList);
1589+
List<ListedItem> fileList = await Win32StorageEnumerator.ListEntries(path, returnformat, hFile, findData, Connection, cancellationToken, -1, intermediateAction: async (intermediateList) =>
1590+
{
1591+
filesAndFolders.AddRange(intermediateList);
1592+
await OrderFilesAndFoldersAsync();
1593+
await ApplyFilesAndFoldersChangesAsync();
1594+
});
1595+
1596+
filesAndFolders.AddRange(fileList);
15901597
await OrderFilesAndFoldersAsync();
15911598
await ApplyFilesAndFoldersChangesAsync();
15921599
});
15931600

1594-
filesAndFolders.AddRange(fileList);
1595-
await OrderFilesAndFoldersAsync();
1596-
await ApplyFilesAndFoldersChangesAsync();
15971601
return 0;
15981602
}
15991603
}
@@ -1607,22 +1611,25 @@ private async Task EnumFromStorageFolderAsync(string path, ListedItem currentFol
16071611
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
16081612
string returnformat = Enum.Parse<TimeStyle>(localSettings.Values[Constants.LocalSettings.DateTimeFormat].ToString()) == TimeStyle.Application ? "D" : "g";
16091613

1610-
List<ListedItem> finalList = await UniversalStorageEnumerator.ListEntries(
1611-
rootFolder,
1612-
currentStorageFolder,
1613-
returnformat,
1614-
sourcePageType,
1615-
cancellationToken,
1616-
-1,
1617-
async (intermediateList) =>
1614+
await Task.Run(async () =>
16181615
{
1619-
filesAndFolders.AddRange(intermediateList);
1616+
List<ListedItem> finalList = await UniversalStorageEnumerator.ListEntries(
1617+
rootFolder,
1618+
currentStorageFolder,
1619+
returnformat,
1620+
sourcePageType,
1621+
cancellationToken,
1622+
-1,
1623+
async (intermediateList) =>
1624+
{
1625+
filesAndFolders.AddRange(intermediateList);
1626+
await OrderFilesAndFoldersAsync();
1627+
await ApplyFilesAndFoldersChangesAsync();
1628+
});
1629+
filesAndFolders.AddRange(finalList);
16201630
await OrderFilesAndFoldersAsync();
16211631
await ApplyFilesAndFoldersChangesAsync();
16221632
});
1623-
filesAndFolders.AddRange(finalList);
1624-
await OrderFilesAndFoldersAsync();
1625-
await ApplyFilesAndFoldersChangesAsync();
16261633

16271634
stopwatch.Stop();
16281635
Debug.WriteLine($"Enumerating items in {path} (device) completed in {stopwatch.ElapsedMilliseconds} milliseconds.\n");

0 commit comments

Comments
 (0)