Pass an object in to a thread in a loop each time in vb.net
I'm not an expert in vb.net so this is kind of a frustrating problem for me. I need read images from a directory and process them parallely. SO ideally what my code should do is,
Dim Directory As New IO.DirectoryInfo("New Folder\\") Dim allFiles As IO.FileInfo() = Directory.GetFiles("*.bmp") Dim singleFile As IO.FileInfo Dim i As Integer = 0 For Each singleFile In allFiles Console.WriteLine(singleFile.FullName) If File.Exists(singleFile.FullName) Then Dim badge As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte) (singleFile.FullName) i = i + 1 Dim checkLabelThread As Thread = New Thread(AddressOf processBadge(badge, i)) End If Next`
Here, processBadge is the function that should process the badge. But Vb.net does not allow me to pass variables in to that function. Is there a work around to fix this and fulfill my requirement? Thanks a lot.
Answers
You can generally do this:
Dim checkLabelThread As Thread = New Thread(Sub() processBadge(badge, i))
Note the replacement of AddressOf with Sub().
However, because you are threading the value of i will update before the thread executes so you'll never get the actual value of i - the loop will have finished so the value will be count of the items in the allFiles array.
So here's what I'd do.
First I'd create an overload of processBadge to make the calling code cleaner. Like this:
Private Sub processBadge(fileInfo As FileInfo, index As Integer) Console.WriteLine(fileInfo.FullName) If File.Exists(fileInfo.FullName) Then Dim badge As Image(Of Bgr, Byte) = _ New Image(Of Bgr, Byte)(singleFile.FullName) processBadge(badge, index) End If End Sub
Then I'd call it using Parallel.ForEach like this:
Dim source = new System.IO.DirectoryInfo("New Folder\\") _ .GetFiles("*.bmp") _ .Select(Function(f, i) New With { .FileInfo = f, .Index = i }) Parallel.ForEach(source, Sub(x) processBadge(x.FileInfo, x.Index))
That won't create too many threads and should maximize the performance.
You could create a class to hold your thread context information (untested code follows):
Public Class BadgeProcessor Private ReadOnly _badge As Image Private ReadOnly _index As Integer Public Sub New(badge As Image, index As Integer) _badge = badge _index = index End Sub Public Sub ProcessBadge() ' do what your processBadge method does here End Sub End Class
And use that in your loop:
If File.Exists(singleFile.FullName) Then Dim badge As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)(singleFile.FullName) i = i + 1 Dim bp As BadgeProcessor = New BadgeProcessor(badge, i) Dim checkLabelThread As Thread = New Thread(AddressOf bp.ProcessBadge) 'checkLabelThread.Start() ? End If
However, if you have 1000 images in the directory, you are going to start 1000 threads, which is probably not going to be what you want. You should probably investigate the Task Parallel Library, which would use a thread pool to limit the concurrent threads to something more reasonable - perhaps a Parallel.ForEach loop.