NameIsPete
NameIsPete

Reputation: 608

Referencing an object (class) within a thread fails

Referencing an object (class) within a thread fails

I have an object ("a vb class") that needs to run on a separate thread and communicate with the U/I.

Even using sample code, I cannot get the object to run within a thread. I demonstrate this problem with two examples. The first calls a function within the form and it works perfectly. The second creates an object and performs the same calls, but fails.


example #1 [working] (Called within a form)

 Private Delegate Sub FuctionToBeRunInThreadDelegate

 Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

    Console.WriteLine("Thread sample within FORM")

    Dim Thread As New System.Threading.Thread(AddressOf FuctionToBeRunInThread)
    Thread.Start()

    Console.WriteLine("Thread sample within FORM completed")

 End Sub

 Public Sub FuctionToBeRunInThread()

    If Me.InvokeRequired Then
        Console.WriteLine("Inside new thread....")
        Me.Invoke(New FuctionToBeRunInThreadDelegate(AddressOf FuctionToBeRunInThread))
    Else
        Console.WriteLine("oFuctionToBeRunInThread")
    End If

  End Sub

The output to the console when the function is called within a form is:
Thread sample within FORM
Thread sample within FORM completed
Inside new thread....
oFuctionToBeRunInThread

This is what I expected. The thread has started asynchronously. Ended very quickly, and the function knows that it is within a thread.




example #2 [non-working] (Calling same function but this time within an object)
In my second example, I use an external file containing a class and create the thread in the same manner.

Here is the main form:

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click

    Console.WriteLine("Thread sample using object started.")

    Dim oEngine As New objTest()
    Dim oThread As New System.Threading.Thread(AddressOf oEngine.oFuctionToBeRunInThread)
    oThread.Start()

    Console.WriteLine("Thread sample using object completed.")


End Sub


Here is the external file containing the class definition:

   Public Class objTest

   Private Delegate Sub oFuctionToBeRunInThreadDelegate()

   Public Sub oFuctionToBeRunInThread()

        If frmInitial.InvokeRequired Then
            Console.WriteLine("Inside new thread....")
            frmInitial.Invoke(New oFuctionToBeRunInThreadDelegate(AddressOf oFuctionToBeRunInThread))
        Else
            Console.WriteLine("oFuctionToBeRunInThread")
        End If

    End Sub
   End Class

In this case, the output is demonstrating that the function is not running in a separate thread. It is as follows:

Thread sample using object started.
Thread sample using object completed.
oFuctionToBeRunInThread



SUMMARY: When the thread creates the object, it appears that the object is not actually running inside of a thread or else form.InvokeRequired would be true. I have other more complex examples where this is strongly verified and evidenced, but I provided these two as a very simple demonstration of my problem.

How can I have a thread "own" a series of individual objects so that the objects are run asynchronously and can independently report back to the U/I?

Upvotes: 1

Views: 1806

Answers (1)

Tawfik Khalifeh
Tawfik Khalifeh

Reputation: 949

after debugging your code, it appears that frmInitial.InvokeRequired is failing to execute correctly.

=======================================================

so am back again (with a solution of course):

Public Class frmInitial

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Console.WriteLine("event started")

        Dim obj As New ObjTest()
        Dim threadobj As New System.Threading.Thread(AddressOf obj.dosomework)
        threadobj.Name = "debugme"

        'passing the current form reference to the thread function
        threadobj.Start(Me)

        Console.WriteLine("event completed")
    End Sub
End Class

screen snapshot

Public Class ObjTest
        Private Delegate Sub dosomeworkDelegate(ByVal f As Form)

        Public Sub dosomework(ByVal f As Form)
            ' Check if the form can be accessed from the current thread.
            If Not f.InvokeRequired Then
                ' Access the form directly.
                Console.WriteLine("delegate executed")
                f.Controls("textbox1").Text = "thread invoked successfuly"
            Else
                ' Marshal to the thread that owns the form. 
                Dim del As dosomeworkDelegate = AddressOf dosomework
                Dim param As Object() = {f}
                Console.WriteLine("executing delegate")
                f.BeginInvoke(del, param)
            End If
        End Sub

End Class

believe me its way better than studying for my numerical analysis exam :-)

Upvotes: 1

Related Questions