【发布时间】:2018-11-12 10:30:17
【问题描述】:
我有一些我正在尝试维护的 UWP 代码。它的目标是将一些保存在目录结构中的纯文本文件合并为一个 XML 文件。
为了这样做,我之前使用 LINQ 抓取了目录结构中所有文件中的所有不同行:
Imports System.IO
Async Function getAllLines() As IEnumerable(Of String)
Dim _folderPicker As New Windows.Storage.Pickers.FolderPicker()
_folderPicker.FileTypeFilter.Add("*") 'We must add this; it is a known bug
Dim _rootDir As Windows.Storage.StorageFolder = Await _folderPicker.PickSingleFolderAsync()
Dim allDistinctLines As IEnumerable(Of String) = From _file In Directory.GetFiles(_rootDir.Name, "*.txt", SearchOption.AllDirectories) From line In File.ReadAllLines(_file) Where line.Trim().Length > 0 Select line.Trim() Distinct
Return allDistinctLines
End Function
然而,自 10 月下旬以来,关于文件权限 (Source) 的一些事情似乎发生了变化。经过大约一个月的工作后,我回到了代码,发现它抛出了一个异常,说我以前能够写入的文件夹由于权限而无法访问。该文件夹存在,我从选择器中抓取了该文件夹,所以我认为我很好。以前,只要我使用选择器抓取了文件或文件夹,我仍然可以使用 System.IO 函数来枚举、读取或写入所述文件夹或目录。
现在,您似乎必须通过适当的 UWP 学院,这很好,但我不确定如何重写我的 LINQ 查询,因为 UWP 方法是异步的。
这是我尝试过的:
Async Function getAllLines() As IEnumerable(Of String)
Dim _folderPicker As New Windows.Storage.Pickers.FolderPicker()
_folderPicker.FileTypeFilter.Add("*") 'We must add this; it is a known bug
Dim _rootDir As Windows.Storage.StorageFolder = Await _folderPicker.PickSingleFolderAsync()
Dim queryOptions As New Windows.Storage.Search.QueryOptions()
queryOptions.FileTypeFilter.Add(".txt")
queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep
Dim allDistinctLines As IEnumerable(Of String) = From _file In Await _rootDir.CreateFileQueryWithOptions(queryOptions).GetFilesAsync() From line In Await Windows.Storage.FileIO.ReadLinesAsync(_file) Where line.Trim().Length > 0 Select line.Trim() Distinct
Return allDistinctLines
End Function
在上面的代码中,如果我注释掉 LINQ 中的第二个等待,我至少能够枚举文件夹。问题是使用 LINQ 查询中的第二个 Await,我无法编译为
'Await' may only be used in a query expression within the first collection expression of the initial 'From' clause or within the collection expression of a 'Join' clause.
所以我阅读了Join 子句,这些子句似乎等同于不同的数据,这并不是我真正想要的。
我大致了解了该错误,似乎 LINQ 查询和异步函数仅具有有限的功能。老实说,我对 LINQ 的了解还不够,无法真正提出这种说法,但那是我的感觉。
我找到了这个答案,它使用 Task.WhenAll() 来促进 LINQ 和 Async 函数的使用,但我无法确切地了解它是如何付诸实践的。
How to await a method in a Linq query
所以我尝试了:
Async Function getAllLines() As IEnumerable(Of String)
Dim _folderPicker As New Windows.Storage.Pickers.FolderPicker()
_folderPicker.FileTypeFilter.Add("*") 'We must add this; it is a known bug
Dim _rootDir As Windows.Storage.StorageFolder = Await _folderPicker.PickSingleFolderAsync()
Dim queryOptions As New Windows.Storage.Search.QueryOptions()
queryOptions.FileTypeFilter.Add(".txt")
queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep
Dim allFiles As IEnumerable(Of Windows.Storage.StorageFile) = From _file In Await _rootDir.CreateFileQueryWithOptions(queryOptions).GetFilesAsync() Select _file
Dim allDistinctLines As IEnumerable(Of String) = Task.WhenAll(allFiles.Select(Function(_file) Windows.Storage.FileIO.ReadLines.Async(_file).Where(Function(_line) _line.Trim().Length > 0).Distinct()))
Return allDistinctLines
End Function
但是返回类型不一样,它最终是一些奇怪的 IList(Of String)(),奇怪的是它对我不起作用。也许这只是一个严重的误解。
无论如何,对理解异步文件操作的任何帮助都非常有用!
【问题讨论】:
-
请查看此案例reply。
-
@CoCalceDew 我看过那个帖子,它包含在我原来的问题中。我需要澄清一下应该如何使用它。任何帮助都会得到帮助。
标签: vb.net linq uwp async-await