我正在努力学习编写通用应用程序,我开始尝试重新创建我在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并点击停止。我可能犯了一些愚蠢的错误,但我无法弄清楚它是什么。
非常感谢任何帮助。
答案 0 :(得分:1)
问题很可能不是由文件访问代码本身引起的,而是由您使用异步API的方式引起的。
由于GetLogFolder
方法返回Task
StorageFolder
,因此您需要等待结果,而不是使用Result
属性获取结果。原因是async/await
模式允许您在单独的线程上执行 I / O工作,但在完成后将控制权返回给UI线程。你在这里做的是调用GetLogFolder
方法,让用户使用FolderPicker
选择一个文件夹。 以下是问题 - 当控件返回到您的代码并且您查询{{1}返回的Result
的{{1}}属性时,会向用户显示文件夹选择器}} 方法。查询Task
属性会导致UI线程停止并等待GetLogFolder
完成以获得结果。不幸的是,当用户选择文件夹时,控件想要返回UI线程继续执行Result
方法的其余部分,并且我们有死锁。 Task
属性阻止UI线程等待GetLogFolder
结果,Result
等待UI线程变为可用。两者都不能继续,所以应用程序完全冻结。
解决方案非常简单 - 使用Task
/ Task
关键字。您可以在VB.NET here with a clear example中阅读有关它们的更多信息。
在你的情况下,第一步是制作按钮的async
处理程序方法await
,然后用以下内容替换代码:
Click