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

C# C中的UWP递归文件搜索非常慢,c#,list,file,uwp,directory,C#,List,File,Uwp,Directory,我使用下面的代码递归搜索选定文件夹中的图像。我在那个文件夹里有超过120000张照片是的,我是摄影师!而且速度非常慢,例如,我必须在10分钟后停止,但它还没有完成。相比之下,我的Python代码被解释了!在不到2分钟的时间内完成同样的操作 有没有办法使这段代码更有效?它工作得很好,没关系,但只是很慢 public List<StorageFile> _allFiles; public List<StorageFile> ShuffledFiles;

我使用下面的代码递归搜索选定文件夹中的图像。我在那个文件夹里有超过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);
    }

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

使用System.IO名称空间;当我切换到那个API时,我注意到我的应用程序有了一些改进

不要试图使用SeaerchAPI来手动迭代它:我认为这是最好的方法

有没有办法使这段代码更有效

源自

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

这意味着系统将创建数据库来记录文件的索引。Windows存储API提供了使用文件索引高效查询文件的功能

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秒内扫描了70000个文件的子树。在我的原始问题中,上面的递归代码需要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(); });
                }
            }
    }

正如下面的答案所说,一定要使用SearchQuery,但也要在GetFileInfolder中将.ConfigureWaitFalse保留到任务结束时,以防止大量的上下文切换。例如,wait folder.GetItemsAsync.AsTask.ConfigureWaitFalse和wait GetFileInfolderItem as StorageFolder.ConfigureWaitFalse这听起来很有趣,但是我得到的应用程序称为接口,该接口作为错误被封送到另一个线程。。。抱歉,我不确定我在做什么……ConfigureWaitFalse本质上告诉代码不要关心返回到它起源的线程,该线程相对昂贵,并且在高产量循环中非常明显。在本例中,这意味着它不会返回到UI线程,这意味着需要使用Dispatcher.RunAsync…..设置cmdbar.Content。。。。。不要等待它。只要您不在LoadMediaFile中配置Wait,它应该是唯一需要调度的地方。酷!ConfigureAwait起到了显著的作用。然而,我仍然不明白为什么我的python代码要快得多?Python会被解释,这会使它变慢。文件访问通过一个单独的进程RuntimeBroker.exe在UWP和interops中进行沙盒处理,所以速度会变慢。UWP中的System.IO也是使用StorageFile API实现的,因此也没有任何好处。如果您正确配置等待,它实际上会稍微慢一点。但是使用Windows Search API按文件类型进行预筛选、进行深度搜索和使用搜索索引应该会带来更大的提升。谢谢!我试过这个,只是稍微快一点。。。。我是否应该尝试只收集列表中的文件名字符串而不是StorageFolder?这会因为创建更大对象的内存管理而有所帮助吗?或者这与磁盘I/O速度有关?使用Windows资源管理器执行类似操作需要一两分钟的时间来处理这些文件夹,因此必须有一种更快的方法…尝试一下:uhhh!!!听起来很有前途,乔治!我会给它一个机会,并报告肯定!我确实修改了代码以使用这种方法,它确实快了10倍。但是,必须使用Windows索引器为文件编制索引。另一件让我不安的事情是,我的Python应用程序intepreted比我计时快了100倍!而不是UWP本机应用程序。这就好像微软愿意放慢电脑的速度。。。。?!?!?我最后也遇到了同样的问题。我正在尝试枚举视频,但文件夹没有索引。我不得不修改它,不使用索引,我很确定我已经失去了速度提升。