vb.net threading.thread addressof passing variables

StealthRT picture StealthRT · Apr 16, 2012 · Viewed 10.5k times · Source

I am trying to pass some status from a IP call in a shared sub to a label on my form.

This is the current code that i am using:

Class Server
    <STAThread()> Public Shared Sub Main()
        Dim aTcpMessaging As IMessagingSystemFactory = New TcpMessagingSystemFactory()
        Dim anInputChannel As IInputChannel = aTcpMessaging.CreateInputChannel(theIPforLocal & ":" & thePort)
        Dim aStringMessagesFactory As IStringMessagesFactory = New StringMessagesFactory()
        Dim aStringMessageReceiver As IStringMessageReceiver = aStringMessagesFactory.CreateStringMessageReceiver()
        AddHandler aStringMessageReceiver.MessageReceived, AddressOf StringMessageReceived

        aStringMessageReceiver.AttachInputChannel(anInputChannel)
    End Sub

    Private Shared Sub StringMessageReceived(ByVal sender As Object, ByVal e As StringMessageEventArgs)
        LANResponse = Convert.ToString(e.Message)
        Dim lanSent As String() = Nothing
        Dim sep(3) As Char
        Dim s As String = ""

        sep(0) = "~"
        'sep(1) = ","
        lanSent = LANResponse.Split(sep, 2)

        Dim a As New Threading.Thread(AddressOf getStatus)

        a.SetApartmentState(Threading.ApartmentState.STA)
        a.Start(Trim(lanSent(0)) & Trim(lanSent(1)))
  End Sub
End Class

Private Shared Sub getStatus(ByVal data As Object)
    lblStatus.text = ("Static: " & data)
End Sub

The error its giving me is on the line lblStatus.text = ("Static: " & data)

Error 1 Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class.

Any help would be great!

David

UPDATE

After adding:

Private Sub getStatus(ByVal data As Object)
    If InvokeRequired Then
        Invoke(New Action(Of Object)(AddressOf getStatus), data)
    Else
        lblStatus.Text = ("Static: " & data)
    End If
End Sub

I get this error no one line Dim a As New Threading.Thread(AddressOf getStatus)

Error 1 Overload resolution failed because no accessible 'New' can be called with these arguments: 'Public Sub New(start As System.Threading.ParameterizedThreadStart)': Reference to a non-shared member requires an object reference. 'Public Sub New(start As System.Threading.ThreadStart)': Method 'Private Sub getStatus(data As Object)' does not have a signature compatible with delegate 'Delegate Sub ThreadStart()'.

Answer

rskar picture rskar · Apr 16, 2012

I've noticed you're trying to make this work using Shared members. That may be problematic for the following reasons:

(1) Without the Shared, behind the scenes a reference variable is created, and it is called Me. Via Me you can get to lblStatus, such as Me.lblStatus, and actually one doesn't necessarily need to put in the Me, one could specify lblStatus by itself. But, even by itself, the Me is implied there, and is still used.

(2) With the Shared, there is no Me. Without the Me, there is no lblStatus instance for the compiler to identify - hence the error. You will need to find some way to pass in a reference to your Form from which to access lblStatus. I need to warn you, though, that updating a Label or other user interface class directly from a thread other than the main thread is regarded as something bad - this is because WinForms is not thread-safe. Beginning with .NET Framework 2, you'll get an error if you try (although it is possible to opt-out of this error, at your own peril).

These are for C#, but it may give you some ideas on how to proceed:

How to update the GUI from another thread in C#?

http://www.codeproject.com/Articles/23517/How-to-Properly-Handle-Cross-thread-Events-and-Upd

So step one is to make getStatus not a shared member - that will bring back the Me.

Step two is to redesign getStatus into a thread-safe form for getting the text into the Label, such as:

Private Sub getStatus(ByVal data As Object)
    If InvokeRequired Then
        Invoke(New Action(Of Object)(AddressOf getStatus), data)
    Else
        lblStatus.Text = ("Static: " & data)
    End If
End Sub

Step three is to find some way to get a reference to your Form into Server - may be via a shared ArrayList? Or just some shared reference to Form?

Step four is a redesign of StringMessageReceived so that the AddressOf portion is now in the form of AddressOf refToMyForm.getStatus.