1

So my use for a module is so I can use the same functions across different programs that I develope for my employer. They also want my module to be distributed amongst other programmers so they can use it as well. The programs need to know when there is a thread still running (SQL code is running (there are no problems with the sql side) and it needs to notify the user when all work is done but the user needs to be able to queue work)

From the main form I am using this code:

Dim thread1 As New System.Threading.Thread(AddressOf ModuleTesting.Testing)
thread1.SetApartmentState(Threading.ApartmentState.STA)
thread1.IsBackground = True
thread1.Name = "ModuleLabelCrossThreading"
thread1.Start()

This is the code for my module:

Public Sub Testing()   
    Form1.threadsrunning += 1

    Form1.accesscontrolsmoduletesting()

    'THIS IS WHERE THE PROGRAM DOES STUFF ILLUSTRATED BY SLEEPING'
    System.Threading.Thread.Sleep(2000)

    Form1.threadsrunning -= 1

    Form1.accesscontrolsmoduletesting()
end sub

The code to access the controls on the main form is

Public Sub accesscontrolsmoduletesting()

    If Me.InvokeRequired = True Then
        Me.Invoke(New MethodInvoker(AddressOf accesscontrolsmoduletesting))
    Else

        If threadsrunning > 0 Then
            Label4.Text = threadsrunning & " threads running"
        Else
            Label4.Text = "0 threads running"
        End If
    End If

End Sub

I already know the issue is the new thread is creating a new form. I tested this by showing the form and making it wait so it didnt immediately dispose itself and I seen the label was updated. How do I make this thread update the main form instead of just creating a new mainform and then disposing itself after the thread dies?

Branden
  • 28
  • 4
  • You are using Form1 in your module, that is the class name of your form, it will use the default form instance, which is not your actual form1. You need to be working on the instance of your form that was created on startup – Mark Hall Dec 31 '13 at 04:57

1 Answers1

4

To reiterate on my Comment you need to get the actual Form1 that is being shown, you should change your Testing Method to accept a Parameter of Form1, then you can use a Parameterized Thread.Start to pass in the Calling Form. You are running into a feature that was left in place to placate Vb6 programmers transitioning to VB.net as this answer by Hans states. And you may find this Blog Post by John Mcllhinney an interesting read.

From Second Link(emphasize mine):

In order to access a form from a secondary thread you generally need to test its InvokeRequired property and then call its Invoke method. I said earlier that there is only ever one default instance of a form class. That’s not strictly true. In fact, default instances are thread-specific, so there is only ever one default instance per thread. As such, if you test the InvokeRequired property of the default instance you will always be accessing the default instance for the current thread, not the one that was displayed on the main thread.

So in response to above I would change your Module Test Method to:

Public Sub Testing(myForm As Form1)
    myForm.threadsrunning += 1

    myForm.accesscontrolsmoduletesting()

    'THIS IS WHERE THE PROGRAM DOES STUFF ILLUSTRATED BY SLEEPING'
    System.Threading.Thread.Sleep(2000)

    myForm.threadsrunning -= 1

    myForm.accesscontrolsmoduletesting()
End Sub

And I would change your Form1's Thread Start Code to look like this.

Dim thread1 As New System.Threading.Thread(AddressOf ModuleTesting.Testing)
thread1.SetApartmentState(Threading.ApartmentState.STA)
thread1.IsBackground = True
thread1.Name = "ModuleLabelCrossThreading"
thread1.Start(Me) 'Note the passing in the instance of the calling Form

After making these few changes your code will work

Community
  • 1
  • 1
Mark Hall
  • 53,938
  • 9
  • 94
  • 111
  • 1
    Thank you for your time in this matter, I read the articles and gained some more insight. Also I changed the code and it worked like you said. I am not that great at multithreaded applications as it is something I do not deal with normally (I am an SQL grunt) but it is interesting to know I can pass a form as a variable to a thread. – Branden Jan 01 '14 at 01:02
  • 1
    @user3148168 You are welcome, I am glad that I was able to help. – Mark Hall Jan 01 '14 at 03:01