Firstly your forum has solved many of my questions in the past, I have had to register to find the solution to this one.

The current application I am working on is multi-threaded and I am really getting confused with VB.NET's way of doing things (ex Java programmer).


A schedule class runs every 60 seconds querying our database for new "Job's" to do. If it finds "Job's" it spawns a Job thread for each job and waits another 60 seconds.

A Job class fetches required "Report's" of the "Job" and spawns a "Report" thread for each of the "Reports". (Note: a report thread can take 1 sec to 20 sec to run)

My problem is, I have implemented a delegate sub in the "Job" class that the "Report" class threads use. Leading to my problem that when two "Job" threads are running the "Report" threads aren't talking back to the correct "Job" thread. The "Report" threads need to pass back the processed data to the "Job" thread for merging.

Are delegates the best way to handle communication between my threads. The examples I have seen the Delegate subs or functions have been in the same class. My problem is that I have had to make it Shared in the Job class so the Report class can see it without having to make an instance of the Job class.

(I would post code, but its a lot of code. Will post snippets soon once I can make it simpler to understand)

Schedule (Polls database for Jobs)
Job (Handles the Job from the database)
Report (Handles the Report part of the Job)

(Sorry for the double post, the edit button has gone)

Here is the code, the problem is illustrated when ran, the Job class expects 3 returns but the "Report" thread return to both classes (6 rather than 3).

I need a way for the report threads to only report to their job thread and not any others running!
(Used to run it as a console application)

Module Module1

    Sub Main()
        Console.WriteLine("(Module) Running schedule prototype")
        Dim schedule As New ScheduleClass()
    End Sub

End Module

The schedule class

Imports System.Threading

Public Class ScheduleClass

    Public Sub run()

            ' Thread name counter
            Dim thread_counter As Integer = 0

            While True

                ' Simulate 2 jobs at once
                newJobThread("Job Thread " & thread_counter.ToString)
                newJobThread("Job Thread " & thread_counter.ToString + 1)
                thread_counter = thread_counter + 1

            End While

        Catch ex As Exception

        End Try

    End Sub

    Private Sub newJobThread(ByVal thread_name As String)
        Dim job As New JobClass(thread_name)
        Dim thread As New Thread(AddressOf job.run)
        thread.Name = thread_name
        thread.Priority = ThreadPriority.Normal
    End Sub
End Class

The Job class

Imports System.Threading

Public Class JobClass

    Dim thread_name As String
    Shared job_data As ArrayList

    Public Sub New(ByVal thread_name As String)
        Me.thread_name = thread_name
        job_data = New ArrayList(3)
        Console.WriteLine("(JobClass) New thread with name: " & Me.thread_name)
    End Sub

    Public Sub run()

        ' Simulate generating 3 reports for the job thread
        newReportThread(Me.thread_name & ": Report Thread 1")
        newReportThread(Me.thread_name & ": Report Thread 2")
        newReportThread(Me.thread_name & ": Report Thread 3")

        While job_data.Count <> 3
            Console.WriteLine("(JobClass) Not all data returned (Only " & job_data.Count & " out of 3)")
        End While

        Console.WriteLine("(JobClass) All data returned now outputing for thread: " & Me.thread_name)

        Dim loop_counter As Integer = 0

        While loop_counter < job_data.Count
            Console.WriteLine("(JobClass) Item(" & loop_counter & ") = " & job_data.Item(loop_counter).ToString)
            loop_counter = loop_counter + 1
        End While

    End Sub

    Private Sub newReportThread(ByVal thread_name As String)
        Dim report As New ReportClass(Me.thread_name & ":" & thread_name)
        Dim thread As New Thread(AddressOf report.run)
        thread.Name = Me.thread_name & ":" & thread_name
        thread.Priority = ThreadPriority.Normal

    End Sub

    Public Shared Sub returnReportThreadData(ByVal data As String)

        SyncLock (job_data)
        End SyncLock

    End Sub
End Class

The Report class

Imports System.Threading

Public Class ReportClass

    Dim thread_name As String

    Public Sub New(ByVal thread_name As String)
        Me.thread_name = thread_name
        Console.WriteLine("(ReportClass) New Report thread: " & Me.thread_name)
    End Sub

    Public Sub run()
        Dim handler As New returnData(AddressOf JobClass.returnReportThreadData)

        Dim rand As New Random

        ' Simulate waiting for the report to be completed
        Thread.Sleep(1000 * rand.Next(1, 5))

        handler.Invoke("Hi from thread: " & Me.thread_name)

    End Sub

    Delegate Sub returnData(ByVal data As String)
End Class