Vb.net 异步和LINQ查询:检索目录树中所有文件中的所有行
我有一些我试图维护的UWP代码。它的目标是将保存在目录结构中的一些纯文本文件合并成一个XML文件 为了做到这一点,我之前使用LINQ获取了directory结构中所有文件中的所有不同行:Vb.net 异步和LINQ查询:检索目录树中所有文件中的所有行,vb.net,linq,uwp,async-await,Vb.net,Linq,Uwp,Async Await,我有一些我试图维护的UWP代码。它的目标是将保存在目录结构中的一些纯文本文件合并成一个XML文件 为了做到这一点,我之前使用LINQ获取了directory结构中所有文件中的所有不同行: Imports System.IO Async Function getAllLines() As IEnumerable(Of String) Dim _folderPicker As New Windows.Storage.Pickers.FolderPicker() _folderPic
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月下旬以来,文件传输任务似乎发生了一些变化。经过大约一个月的工作后,我回到代码中,发现它抛出了一个异常,表示由于权限原因,我以前可以写入的文件夹无法访问。文件夹存在,我从一个拾荒者那里抓到了文件夹,所以我觉得我很好。以前,只要我使用选择器抓取了一个文件或文件夹,我仍然可以使用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中的第二个wait,我至少能够枚举文件夹。问题是,对于LINQ查询中的第二个wait,我无法编译为
'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查询和异步函数的功能有限。老实说,我对林克的了解还不足以让我做出这样的声明,但那是我的感觉
我找到了这个答案,它使用Task.WhenAll()来促进LINQ和异步函数的使用,但我不知道如何将其付诸实践
所以我试着:
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(字符串的)(),这对我来说并不奇怪。也许这只是一个严重的误解
无论如何,任何帮助理解异步文件操作都是值得的 正如Stephen在本文中所说,LINQ对async/await
的支持非常有限。我建议您将每个与api结合使用,如下所示:
Async Function getAllLines() As Task(Of 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 New List(Of String)
For Each file As StorageFile In Await _rootDir.CreateFileQueryWithOptions(queryOptions).GetFilesAsync()
For Each line In Await Windows.Storage.FileIO.ReadLinesAsync(file)
If line.Trim().Length > 0 Then
allDistinctLines.Add(line.Trim())
End If
Next
Next
Return allDistinctLines.Distinct()
End Function
请检查这个案例。@CoCalceDew我已经看到了那个帖子,它包含在我最初的问题中。我需要一些关于如何利用它的澄清。任何帮助都将不胜感激。谢谢你的回答。有趣的是,这与我最终生成的当前正在工作的代码几乎相同。我真的很享受能够生成一行非常强大、单一的代码,将文件枚举到我指定的深度,同时检索不同的行。当然,我可以写一个扩展,但如果不是太夸张的话,这似乎有点失去了表达力。尽管如此,我测试中的枚举完成得更快,并不是说应用程序更好;我需要枚举的文件生成总大小小于1MB的xml