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

时间:2018-09-07 03:41:00

标签: c# list file uwp directory

我正在使用以下代码来递归搜索所选文件夹中的图像。该文件夹中有超过120000张图像(是的,我是摄影师!),而且速度非常慢,例如我必须在10分钟后将其停止,但尚未完成。相比之下,我的Python代码(解释了!)在不到2分钟的时间内完成了相同的工作。

有什么方法可以使此代码更高效?它工作正常,没关系,但只能非常缓慢...

    public List<StorageFile> _allFiles;
    public List<StorageFile> 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<StorageFolder> 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<StorageFile>();
        numfiles = 0;
        //Reads the files recursively into the list
        await GetFilesInFolder(root);
    }

3 个答案:

答案 0 :(得分:1)

我没有太多照片可以快速测试,但是您可以尝试两件事。

  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(我认为这是最好的方法)

答案 1 :(得分:0)

  

有什么方法可以使这段代码更高效?

源自Universal Windows Platform - File System Monitoring in Universal Windows Platform Apps

  

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

这意味着系统将创建数据库来记录文件的索引。 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;

您可以参考这个相关的博客。   Change Tracking: More Betterness

答案 2 :(得分:0)

好,尝试使用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<string> fileTypeFilter = new List<string>();
            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(); });
                }
            }
    }