如何读取通用应用程序中的任意文件夹?

How to read an arbitrary folder in a Universal app?

我正在尝试学习编写通用应用程序,我开始尝试重新创建我在 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

但是好像不行。在此阶段,我有一个仅包含 TextBlock 和 Button 的表单。单击 Button 将调用一个方法,该方法将解析给定文件夹中的所有 *.log 文件。它做的第一件事是:

Dim myFolder As StorageFolder = GetLogFolder.Result

当代码运行时,我单击按钮,显示了一个文件夹浏览器对话框,但随后一切都冻结了,我必须切换到 Visual Studio 并单击停止。我可能犯了一些愚蠢的错误,但我不知道它是什么。

如有任何帮助,我们将不胜感激。

问题很可能不是文件访问代码本身引起的,而是你使用异步的方式引起的API。

因为 GetLogFolder 方法 return 是 StorageFolderTask,您将需要等待结果,而不是使用 Result 属性。原因是 async/await 模式允许您在单独的线程上执行 I/O 工作,但 return 控制权在完成后返回 UI 线程。您在这里所做的是调用 GetLogFolder 方法,在该方法中您让用户使用 FolderPicker 选择文件夹。 这就是问题所在 - 用户看到一个文件夹选择器,而控件 return 进入您的代码并且您查询 Result 属性 Task return 由 GetLogFolder 方法编辑。查询 Result 属性 导致 UI 线程停止并等待 Task 完成以获取结果。不幸的是,当用户选择文件夹时,控件想要 return 到 UI 线程以继续执行 GetLogFolder 方法的其余部分,我们有一个 死锁 Result 属性 停止了 UI 线程等待 Task 结果,Task 等待 UI 线程可用。两者都无法继续,因此应用程序完全冻结。

解决方案非常简单 - 使用 async / await 关键字。您可以在 VB.NET here with a clear example.

中阅读更多关于它们的信息

在您的情况下,第一步是创建按钮的 Click 处理程序方法 async,然后将其中的代码替换为以下内容:

Dim myFolder As StorageFolder = Await GetLogFolder