问题
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()'.
回答1:
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
.
回答2:
You need to use Delegate Example for your case:
Public Delegate Sub AddLabelTextDelegate(ByVal label As LabelControl, ByVal value As String)
Public Sub AddLabelText(ByVal label As LabelControl, ByVal value As String)
label.Text = value
End Sub
Then from your other thread you need to invoke:
Me.lblStatus.Invoke(New AddLabelTextDelegate(AddressOf AddLabelText), New Object(){lblStatus, "Value"})
来源:https://stackoverflow.com/questions/10180898/vb-net-threading-thread-addressof-passing-variables