如果您确定解析总是比读取快,您可以非常简单地做到这一点:线程 A(只是一个不阻塞 UI 线程的线程)读取文件,然后启动一个新线程 B 并将文件内容传递给它(使用任务而不是线程更容易)。把它放到一个循环中,你就完成了。由于解析速度更快,第二个线程/任务将在线程 A 启动新线程之前完成。因此,您将只有两个线程同时运行,并且同时在内存中运行 2 个文件。
等待获取线过程完成。解析线程应该知道是否有准备解析数组。
不确定我是否理解正确,但这将通过上述“解决方案”来解决。因为您总是启动一个新的线程/任务,何时且仅当文件已被完全读取时。
更新:如果处理不是(总是)比阅读快,你可以这样做,例如:
Private MaxTasks As Integer = 4
Private Async Sub ReadAndProcess(ByVal FileList As List(Of String))
Dim ProcessTasks As New List(Of Task)
For Each fi In FileList
Dim tmp = fi
Console.WriteLine("Reading {0}", tmp)
Dim FileContent = Await Task.Run(Of Byte())(Function() As Byte()
Return File.ReadAllBytes(tmp)
End Function)
If ProcessTasks.Count >= MaxTasks Then
Console.WriteLine("I have to wait!")
Dim NextReady = Await Task.WhenAny(ProcessTasks)
ProcessTasks.Remove(NextReady)
End If
Console.WriteLine("I can start a new process-task!")
ProcessTasks.Add(Task.Run(Sub()
Console.WriteLine("Processing {0}", tmp)
Dim l As Long
For Each b In FileContent
l += b
Next
System.Threading.Thread.Sleep(2000)
Console.WriteLine("Done with {0}", tmp)
End Sub))
Next
Await Task.WhenAll(ProcessTasks)
End Sub
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ofd As New OpenFileDialog
ofd.Multiselect = True
If ofd.ShowDialog = Windows.Forms.DialogResult.OK AndAlso ofd.FileNames.Count >= 1 Then
ReadAndProcess(ofd.FileNames.ToList)
End If
End Sub
这个想法(通常可以在 .Net 中以 4 种方式实现)很简单,您可以安排新的处理任务,直到达到您自己设定的限制。如果达到这一点,您“等待”直到任务准备好并开始新的任务。
UPDATE2:使用 TPL lib 它可能看起来像:
Private Sub Doit()
Dim ABProcess As New ActionBlock(Of Tuple(Of String, Byte()))(Sub(tp)
Console.WriteLine("Processing {0}", tp.Item1)
Dim l As Long
For Each el In tp.Item2
l += el
Next
System.Threading.Thread.Sleep(1000)
Console.WriteLine("Done with {0}", tp.Item1)
End Sub, New ExecutionDataflowBlockOptions With {.MaxDegreeOfParallelism = 4, .BoundedCapacity = 4})
Dim ABRead As New ActionBlock(Of String())(Async Sub(sarr)
For Each s In sarr
Console.WriteLine("Reading {0}", s)
Dim t = New Tuple(Of String, Byte())(s, File.ReadAllBytes(s))
Dim taken = Await ABProcess.SendAsync(t)
Console.WriteLine("Output taken = {0}", taken)
Next
Console.WriteLine("All reading done")
End Sub)
Dim ofd As New OpenFileDialog
ofd.Multiselect = True
If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
ABRead.Post(ofd.FileNames)
End If
End Sub
哪个版本“更好”......可能是个人口味;)我个人可能更喜欢“手动”版本,因为新的 TPL 块有时非常黑箱。