C#中的UWP递归文件搜索速度非常慢

我使用以下代码以递归方式搜索所选文件夹中的图像。 我在该文件夹中有超过120000张图像(是的,我是一名摄影师!)而且它非常慢,例如我必须在10分钟后停止它并且还没有完成。 相比之下,我的Python代码(解释!)在不到2分钟内完成相同的操作。

有没有办法让这个代码更有效率? 它工作正常,没关系,但只是非常缓慢……

public List _allFiles; public List ShuffledFiles; public int i = 0; public int ri = 0; public Boolean random = false; public int numfiles = 0; //Get the starting folder for recursive search private static async Task SelectFolderAsync() { var folderPicker = new Windows.Storage.Pickers.FolderPicker { SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop }; //Selects the folder with a FolderPicker and returns the selected StorageFolder folderPicker.FileTypeFilter.Add("*"); StorageFolder folder = await folderPicker.PickSingleFolderAsync(); return folder; } //Get the list of files recursively private async Task GetFilesInFolder(StorageFolder folder) { var items = await folder.GetItemsAsync(); foreach (var item in items) { //If it's a folder, read each file in it and add them to the list of files "_allFiles" if (item is StorageFile ) { StorageFile typetest = item as StorageFile; String ext = typetest.FileType.ToLower(); if ((ext == ".jpg") || (ext == ".jpeg") || (ext == ".tiff") || (ext == ".cr2") || (ext == ".nef") || (ext == ".bmp") || (ext == ".png")) { _allFiles.Add(item as StorageFile); numfiles = numfiles + 1; //Display the file count so I can track where it's at... cmdbar.Content = "Number of slides:"+numfiles.ToString(); } } else //otherwise, recursively search the folder await GetFilesInFolder(item as StorageFolder); } } //Select the directory, load the files and display the first file private async void LoadMediaFile(object sender, TappedRoutedEventArgs e) { StorageFolder root = await SelectFolderAsync(); //Initialises the file list _allFiles, the filecount numfiles, and the pointers to the list i and ri _allFiles = new List(); numfiles = 0; //Reads the files recursively into the list await GetFilesInFolder(root); } 

我没有那么多照片,我很快就可以测试,但你可以尝试两件事。

  1. 使用System.IO命名空间; 当我切换到该API时,我发现我的应用程序有一些改进。

  2. 不要通过尝试使用seaerch api手动迭代它: https ://docs.microsoft.com/en-us/windows/uwp/files/quickstart-listing-files-and-folders#query-files-in -a-location-and-enumerate-matching-files (我认为这是最好的方法)

有没有办法让这个代码更有效率?

来自通用Windows平台 – 通用Windows平台应用程序中的文件系统监控

系统现在能够提供库中发生的所有更改的列表,从一直拍摄的照片到要删除的整个文件夹。 如果您希望构建云备份提供程序,跟踪从设备移出的文件,甚至只显示最新的照片,这将是一个巨大的帮助。

这意味着系统将创建数据库来记录文件的索引。 Windows Storage API提供了CreateFileQueryWithOptions ,它使用文件索引有效地查询文件。

 StorageFolder photos = KnownFolders.CameraRoll; // Create a query containing all the files your app will be tracking QueryOptions option = new QueryOptions(CommonFileQuery.DefaultQuery, supportedExtentions); option.FolderDepth = FolderDepth.Shallow; // This is important because you are going to use indexer for notifications option.IndexerOption = IndexerOption.UseIndexerWhenAvailable; StorageFileQueryResult resultSet = photos.CreateFileQueryWithOptions(option); // Indicate to the system the app is ready to change track await resultSet.GetFilesAsync(0, 1); // Attach an event handler for when something changes on the system resultSet.ContentsChanged += resultSet_ContentsChanged; 

你可以参考这个相关的博客。 变更跟踪:更好

好的,尝试使用Windows.Storage.Search API。 使用下面的代码,我在1分45秒内扫描70,000个文件的子树。 上面的递归代码(在我的原始问题中)需要1分32秒(更快……!)。 有趣的是,我会认为递归代码会花费更多的时间和资源,因为它有更多的开销?!?!?!

而我的Python解释代码只需3秒! 为了同样的事情!

必须有更好的方法,不是吗? 微软工程师,任何提示?

  //This code is actually taken almost literally from the Microsoft example // given here: https://docs.microsoft.com/en-us/uwp/api/windows.storage.search.queryoptions private async Task GetFilesInFolder(StorageFolder folder) { List fileTypeFilter = new List(); fileTypeFilter.Add(".png"); fileTypeFilter.Add(".jpg"); fileTypeFilter.Add(".jpeg"); fileTypeFilter.Add(".tiff"); fileTypeFilter.Add(".nef"); fileTypeFilter.Add(".cr2"); fileTypeFilter.Add(".bmp"); QueryOptions queryOptions = new QueryOptions(Windows.Storage.Search.CommonFileQuery.OrderByName, fileTypeFilter); queryOptions.FolderDepth = FolderDepth.Deep; queryOptions.IndexerOption = IndexerOption.UseIndexerWhenAvailable; StorageFileQueryResult queryResult = folder.CreateFileQueryWithOptions(queryOptions); var files = await queryResult.GetFilesAsync(); if (files.Count == 0) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { cmdbar.Content = "Nothing found!" ; }); } else { // Add each file to the list of files (this takes 2 seconds) foreach (StorageFile file in files) { _allFiles.Add(file as StorageFile); numfiles = numfiles + 1; //Display the file count so I can track where it's at... await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { cmdbar.Content = "Number of slides:" + numfiles.ToString(); }); } } }