Why does my Label not update ?

Poppa Mintin

Well-known member
Joined
Jan 4, 2018
Messages
45
Programming Experience
10+
Hi,

This is the first relevant Public Sub on Form1:
VB.NET:
Public Sub Client_Accept(ByVal state As Object)
        Try
            palPC.EndConnect(C_Token)
            C_Token = Nothing
        Catch ex As Exception
            'MsgBox("Client_Accept :" & vbCrLf & ex.ToString)
        End Try
        If palPC.Connected Then
            boss = True
        Else
            UpDate(Form3.Label1, "Sorry... " & palName & "  didn't accept!")
        End If
    End Sub ' Client: Connected to Server... Or not.not.

When I run the app. and the connection fails, 'palPC' dosn't connect, the Exception exectutes.
When I click the OK on the MessageBox I expect the code to proceed to:

'If palPC.Connected Then', and since palPC didn't connect I expect Form3 Label1 to up-date, but it doesn't.

Here is the update code, which is also in Form1:
VB.NET:
    Public Sub UpDate(ByVal Lab As Label, ByVal txt As String)
        If Me.InvokeRequired Then
            Me.Invoke(Sub() UpDate(Lab, txt))
        Else
            Lab.Text = txt
            Lab.Refresh()
        End If
    End Sub
Using a breakPoint I can see that:

Lab.Name = "Label1"
txt = "Sorry... MSI didn't accept!"

I was concerned that ' Lab.Name = "Label1" ', I expected to see "Form3.Label1".

There are three forms in this test project, and running a test on this part of the app. Form3's Label1 doesn't update, but neither does the Label1 on Form1 which may've shed a bit of light on the matter had it done.

I don't believe the fault is in the Client_Accept subroutine because when palPC does connect, everything else works correctly.
I only discovered this problem when I deliberately tried to connect to a computer that's not listening for the request. (To check that the code works).
Also, the up-date subroutine works everywhere else in the app. here for example is a line from a different subroutine, also in Form1 which does work:

UpDate(Form3.Label1, "I will be the Red player." & vbCrLf & vbCrLf & "Inviting " & palName & " to play.")

I see that in this case 'Lab.Name' is also just "Form1".
Ah! bother... but the invoke wasn't required, but I think that it shows that the rest of the subroutine works as it ought.

Single stepping through the Client_Accept subroutine code to: ' txt = "Sorry... MSI didn't accept!" ', control passes to the UpDate subroutine and at this point the invoke is required and I can watch the instructions being completed, yet when they are done and Form3 is 'Shown' again, Label1 is just as it was previously.


Poppa.
 
That first method is executed on a secondary thread. You are referring to the default instance of Form3 in that code. Default instances are thread-specific. You are referring to a different form to the one you are looking at. Basically, stay away from default instances. They really don't add anything for anyone but a rank beginner. If you need to refer to an instance of Form3 then you should have a reference to that instance.
 
I was concerned that ' Lab.Name = "Label1" ', I expected to see "Form3.Label1".
I'm not sure why you expected to see that. That is unrelated to your problem but the name of the parent for or control is not part of the Name property of a control. The reference you use in code is unrelated to the value of that property.
 
That first method is executed on a secondary thread. You are referring to the default instance of Form3 in that code. Default instances are thread-specific. You are referring to a different form to the one you are looking at. Basically, stay away from default instances. They really don't add anything for anyone but a rank beginner. [highlight]If you need to refer to an instance of Form3 then you should have a reference to that instance.[/highlight]

Thanks jmcilhinney,

I may be a rank beginner, I didn't start programming until January 1978, but because BASIC has changed so much and so often I may not have kept up-to-date as much as folk who work with the latest versions all the time.

I have no idea what the highlighted part of your reply means.


Poppa.
 
Follow the Blog link in my signature below and check out my post on Default Form Instances.

Thanks, I'll do that.

I've been 'Searching' in MSDN, I entered 'reference to an instance, vb.net, VS2017' and set the option to only look at 'Library' entries.

Where do I start looking: -
"Results 1-20 of about 1,050,000 for: reference to an instance, vb.net, VS2017" !

The first dozen or so that I looked at might as well've been written in Greek. (The only language I don't understand)

Poppa.

PS. Most languages are Greek to me.

Pop.
 
You do know what I'm talking about. You just don't realise it.
Dim myVar = New SomeClass

The myVar variable now contains a reference to an instance of the SomeClass type. You can refer to that object via that variable. If SomeClass was Form1 then myVar would refer to an instance of Form1. If you display that instance and you want to modify that instance later then you need to refer to that instance, not some other instance. Modifying the default instance for another thread will have no effect on the instance referred to by myVar, and why would you expect it to? If you turn on your TV, do you expect other TVs of the same make and model to turn on too? Of course not. That's not the way objects work, in real life or in OOP.
 
Sorry John, I'm still not getting anywhere I might as well take up knitting.

I've read, what I think is, the relevant part of your blog and played with your 'Multiple Forms' example, which works as described. Where I'm having trouble is when I'm TCP multi threading and need to up-date Form3 from Form1, any other time it's a simple case of: 'Form3.Label1.Text = ' etc.
I'm trying to up-date any of the Labels on any of the Forms (1, 2 or 3) from one subroutine in Form1. I could write code for each individual case but I think 'one sub. for all' ought to be achievable.

I chose the name 'Opener' for the variable for Form3, I've tried each of these :
VB.NET:
Private Opener As Form3
Dim Opener As Form3
Public Opener As Form3


Private WithEvents Opener As Form3
Dim WithEvents Opener As Form3
Public WithEvents Opener As Form3

' And each of the above in the form of:

Private Opener As Form = Form3

And tried to use it in my 'Update' subroutine like this:
VB.NET:
UpDate(Opener.Label1, "Sorry... " & palName & "  didn't accept!")
And like this on it's own:
VB.NET:
Opener.Label1.text = "Sorry... " & palName & "  didn't accept!")
Using the '= Form3' versions Intellisense gives the error: 'Label1' is not a member of 'Form'.

Using 'Private Opener As Form3' I get no errors until I run the app. when I get: 'Opener was Nothing'.

And using 'Private WithEvents Opener As Form3' I get no errors until I run the app. when I get:
'Checkout.Form1.Opener.get returned Nothing'.

I guess I'm missing something vital, but can't see what or where.



Poppa.
 
Back
Top