Reputation: 608
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
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
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