Как прочитать произвольную папку в универсальном приложении?

#vb.net #uwp #windows-10-universal

#vb.net #uwp #windows-10-универсальный

Вопрос:

Я пытаюсь научиться писать универсальные приложения, и я начинаю с попытки воссоздать другой проект, который я написал в WinForms. Мне нужно иметь возможность читать файлы журналов в произвольной папке, и, насколько я понимаю, мне нужно получить разрешения пользователей на доступ к папке. Затем я должен сохранить токен доступа, чтобы в будущем я мог перечитывать эту папку. Читая, мне удалось собрать следующий код:

 Friend Async Function GetLogFolder() As Task(Of StorageFolder)
    Dim myLogFolder As StorageFolder
    If ApplicationData.Current.LocalSettings.Values.ContainsKey("LogFolder") Then
        Dim sToken As String = ApplicationData.Current.LocalSettings.Values("LogFolder")
        myLogFolder = StorageApplicationPermissions.FutureAccessList.GetFileAsync(sToken)
    Else
        Dim myFolderPicker As FolderPicker = New FolderPicker
        myFolderPicker.FileTypeFilter.Add("*")
        myLogFolder = Await myFolderPicker.PickSingleFolderAsync

        Dim sToken As String = StorageApplicationPermissions.FutureAccessList.Add(myLogFolder)
        ApplicationData.Current.LocalSettings.Values.Add("LogFolder", sToken)
    End If
    Return myLogFolder
End Function
 

Но, похоже, это не работает. На данном этапе у меня есть форма, содержащая только текстовый блок и кнопку. Нажатие кнопки вызывает метод, который проанализирует все файлы * .log в данной папке. Первое, что он делает, это:

 Dim myFolder As StorageFolder = GetLogFolder.Result
 

Когда код запускается, и я нажимаю кнопку, я получаю диалоговое окно браузера папок, но затем все зависает, и я должен переключиться на Visual Studio и нажать стоп. Вероятно, я допустил какую-то глупую ошибку, но я не могу понять, что это такое.

Любая помощь была бы очень признательна.

Ответ №1:

Проблема, скорее всего, вызвана не самим кодом доступа к файлам, а тем, как вы используете асинхронный API.

Поскольку GetLogFolder метод возвращает Task значение of StorageFolder , вам нужно будет дождаться результата, а не получать его с помощью Result свойства. Причина в том, что async/await шаблон позволяет выполнять операции ввода-вывода в отдельном потоке, но по завершении возвращает управление обратно в поток пользовательского интерфейса. Что вы здесь делаете, так это вызываете GetLogFolder метод, в котором вы позволяете пользователю выбирать папку, используя FolderPicker . Вот в чем проблема — пользователю предоставляется средство выбора папок, в то время как элемент управления возвращается к вашему коду, и вы запрашиваете Result свойство Task , возвращаемое GetLogFolder методом. Запрос Result свойства приводит к остановке потока пользовательского интерфейса и ожиданию Task завершения, чтобы получить результат. К сожалению, когда пользователь выбирает папку, элемент управления хочет вернуться в поток пользовательского интерфейса, чтобы продолжить выполнение остальной части GetLogFolder метода, и мы имеем тупик. Result свойство остановило поток пользовательского интерфейса, чтобы дождаться Task результата, и Task ожидает, пока поток пользовательского интерфейса станет доступным. Ни один из них не может продолжаться, поэтому приложение полностью зависает.

Решение довольно простое — использование async await ключевых слов / . Вы можете прочитать больше о них в VB.NET вот с наглядным примером.

В вашем случае первым шагом было бы создать Click метод обработчика кнопки async , а затем заменить код внутри следующим образом:

 Dim myFolder As StorageFolder = Await GetLogFolder