StorageFileQueryResult.GetFilesAsync () правильное использование с IndexerOption в UWP - PullRequest
0 голосов
/ 07 ноября 2019

Мне интересно, является ли следующее сообщение об ошибке или, в лучшем случае, неточностью документации Windows Search API для StorageFolder.

Это простое приложение UWP, которое позволяет пользователю выбрать папку иГлубоко просканируйте эту папку, чтобы просто посчитать количество файлов.

Возвращенное количество соответствует Windows 10 File Explorer, если папка находится здесь некоторое время, но не согласуется, если папка была только что скопирована в Cдиск из другого раздела на моем ноутбуке. Чтобы прояснить проблему, я скопировал папку с файлами 1768 видео и изображений на рабочий стол и сразу же запустил приложение, чтобы у Windows 10 не было времени для индексации содержимого.

Код C # (XAML прост и может быть угадан из кода C #)

    private async void AppBarButton_Click(object sender, RoutedEventArgs e)
    {
        var folderPicker = new FolderPicker
        {
            SuggestedStartLocation = PickerLocationId.Desktop,
            ViewMode = PickerViewMode.Thumbnail

        };

        folderPicker.FileTypeFilter.Add("*");

        _folder = await folderPicker.PickSingleFolderAsync();
        if (_folder != null)
        {
            resultStackPanel.Children.Clear();
            var indexState = await _folder.GetIndexedStateAsync();
            bottomInfoTextBlock.Text = indexState.ToString();
            var queryOptions = new QueryOptions { FolderDepth = FolderDepth.Deep };
            foreach (IndexerOption indexerOption in Enum.GetValues(typeof(IndexerOption)))
            {
                queryOptions.IndexerOption = indexerOption;
                await CountFilesAsync(queryOptions);
            }
        }
    }

    private async Task CountFilesAsync(QueryOptions queryOptions)
    {
        var textBlock = new TextBlock();
        resultStackPanel.Children.Add(textBlock);

        if (!_folder.AreQueryOptionsSupported(queryOptions))
        {
            textBlock.Text = $"Query unsupported for {queryOptions.IndexerOption}";
            return;
        }
        var query = _folder.CreateFileQueryWithOptions(queryOptions);

        textBlock.Text = $"{queryOptions.IndexerOption}: Wait, getting files count ...";
        var numOfFiles = (await query.GetFilesAsync()).Count;
        textBlock.Text = $"{queryOptions.IndexerOption} {numOfFiles}";
    }
}

Я получаю следующий результат, проходя цикл по IndexerOption Enum

Scan folder result

Я ожидал, что IndexerOption.UseIndexerWhenAvailable вернет точное число 1768, как это задокументировано как

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

Меня беспокоит то, что я хотел бы избежать использования значения DoNotUseIndexer Enum из-запроизводительность, поскольку я планирую получать миниатюры и дополнительные свойства из каждого файла хранилища, но этот параметр является единственным, который дает правильное количество.

Я проверил, что приложение Photos от Microsoft загружает только частьКонтент, т. е. как если бы он использовал UseIndexerWhenAvailable, но у него есть возможность обновляться, пока я жду 1-2 минуты.

Поэтому мне интересно, если:

1) Мой единственныйРешение предоставить пользователю точный результат состоит в том, чтобы использовать DoNotUseIndexer Enum или возможно UseIndexerWhenAvailable или, в идеале, OnlyUseIndexerAndOptimizeForIndexedProperties, но отслеживать какое-то событие, когда Windows 10 в конечном итоге проиндексировала все файлы, чтобы уведомить мое приложение?

2) Что на самом деле делает UseIndexerWhenAvailable? Кажется несовместимым с его описанием

Спасибо

1 Ответ

1 голос
/ 07 ноября 2019

Следующее позволяет информировать приложение об изменении файловой системы. В вызывающем методе вызовите событие

            query.ContentsChanged += Query_ContentsChanged;

с

   private async void Query_ContentsChanged(IStorageQueryResultBase sender, object args)
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
            var count = await sender.GetItemCountAsync();
            var textBlock = new TextBlock();
            resultStackPanel.Children.Add(textBlock);
            textBlock.Text = $"Changed {count} {sender.Folder.Name}";
        });
    }

Локальная переменная count может быть установлена ​​в качестве свойства на странице и, например, OneWay связана сXAML TextBlock.Text с INotifyPropertyChanged. Таким образом, значение будет обновляться по мере того, как Windows индексирует все файлы, и через минуту или около того счетчик достигает конечного значения 1768. Кроме того, удаление или добавление файлов в папке обновит счетчик пользовательского интерфейса. Единственное предупреждение - если вы переименуете папку в какой-то момент. В этом случае приложение начнет подсчет по умолчанию SuggestedStartLocation, в моем случае это рабочий стол. Следовательно, полезность проверки sender.Folder.Name по выбранному _folder (код не показан).

...