UWP Рекурсивный поиск файлов в C # ужасно медленный - PullRequest
0 голосов
/ 07 сентября 2018

Я использую следующий код для рекурсивного поиска изображений в выбранной папке. В этой папке более 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 голосов
/ 10 сентября 2018

Есть ли способ сделать этот код более эффективным?

Производные от Универсальная платформа 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;

И этот блог, на который вы могли бы сослаться. Отслеживание изменений: больше Betterness .

0 голосов
/ 10 сентября 2018

Хорошо, попытался использовать API Windows.Storage.Search. Используя приведенный ниже код, я сканирую поддерево из 70 000 файлов за 1 мин 45 с. Приведенный выше рекурсивный код (в моем исходном вопросе) занимает 1 минуту 32 секунды (быстрее ...!). Интересно, что я подумал бы, что рекурсивный код занял бы больше времени и ресурсов, потому что у него больше накладных расходов!!?!?!

И мой интерпретируемый код на Python занимает всего 3 секунды !!! За одно и то же !!!

Должен быть лучший способ, нет? Инженеры Microsoft вокруг, какие-нибудь намеки?

    //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(); });
                }
            }
    }
0 голосов
/ 07 сентября 2018

У меня не так много фотографий, которые я могу быстро проверить, но есть две вещи, которые вы можете попробовать.

  1. Использовать пространство имен System.IO; Я заметил некоторые улучшения в моем приложении, когда я переключился на этот API.

  2. Не перебирайте вручную, пытаясь использовать API Seaerch: https://docs.microsoft.com/en-us/windows/uwp/files/quickstart-listing-files-and-folders#query-files-in-a-location-and-enumerate-matching-files (я думаю, что будет лучшим подходом)

...