If you are sure, that parsing is ALWAYS faster than reading, you can do it very simple:
Thread A (simply a thread to not block the UI-Thread) reads the file and then starts a new thread B and passes the file content to it (using Tasks instead of thread makes it easier). Put it into a loop and you are done.
Since the parsing is faster, the second thread/task will have finished before Thread A starts a new thread. So you will only have two threads running at the same time and 2 files in memory at the same time.
waiting for the obtaining-lines process to be completed. The parsing thread should know whether there is a ready to parse array.
Not sure if I understand it correctly, but that would be solved by the above "solution". Because you always start a new thread/task, WHEN and only when the file has been read completely.
UPDATE: If processing is NOT (always) faster than reading, your could do it for example like this:
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
The idea (which as usually could be implemented in 4 dozen ways in .Net) is simply, that you schedule new processing tasks until you reach your self-set limit. If that is reached you "wait" until a task becomes ready and start a new one.
UPDATE2: With TPL lib it might look like:
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
Which version is "nicer" ... might be personal taste ;) Personally I might prefer the "manual" version, because the new TPL Blocks are sometimes VERY blackboxish.