Results 1 to 5 of 5

Thread: Custom class varables & multi-threading

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jan 2016
    Posts
    216

    Custom class varables & multi-threading

    I have a problem (so true..)

    I have a program that uses several threads to get things done (simple enough).

    However I recently discovered how to create my own class variables (*cheer*). So I decided to re-code my program to use these new variables (and thus cut huge chunks of extra code out). my problem is this.. I have a variable (Client) being "set" with a "new" statement inside a secondary thread (the cues to create it come from another computer via a port listener, and that part works fine), but when i try to access this variable outside the thread it responds as "nothing". this didn't happen before with basic variables (strings, Boolean, integers, etc) so I can only assume that I'm missing something really obvious in my class creation.

    Can someone point me to the solution?

    Code:
    Namespace CardData
        Public Class Card
            Public Property Suit() As CardSuit
                Get
                    Return m_Suit
                End Get
                Set
                    m_Suit = Value
                End Set
            End Property
            Private m_Suit As CardSuit
            Public Property Value() As CardValue
                Get
                    Return m_Value
                End Get
                Set
                    m_Value = Value
                End Set
            End Property
            Private m_Value As CardValue
            Public Property Score() As Integer
                Get
                    Return m_Score
                End Get
                Set
                    m_Score = Value
                End Set
            End Property
            Private m_Score As Integer
    
            Public ReadOnly Property DisplayValue() As String
                Get
                    Return Suit.ToString() + " " + Value.ToString()
                End Get
            End Property
        End Class
    
        Public Class Client
            Public Property PlayerHand() As List(Of Card)
                Get
                    Return m_PlayerHand
                End Get
                Set
                    If Value.Equals(m_PlayerHand) Then Return
                    m_PlayerHand = Value
                    If IsNothing(m_PlayerHand) Then Return
                    PopulatePlayerCards()
                End Set
            End Property
            Private m_PlayerHand As New List(Of Card)
            Public Property PlayerSent() As List(Of Card)
                Get
                    Return m_PlayerSent
                End Get
                Set
                    m_PlayerSent = Value
                End Set
            End Property
            Private m_PlayerSent As New List(Of Card)
            Public Property HostHand() As Played
                Get
                    Return m_HostHand
                End Get
                Set
                    If Value.Equals(m_HostHand) Then Return
                    m_HostHand = Value
                    Client_Window.PopulateHostCards()
                End Set
            End Property
            Private m_HostHand As New Played
            Public Property Myturn As Boolean
                Get
                    Return m_Myturn
                End Get
                Set
                    m_Myturn = Value
                End Set
            End Property
            Private m_Myturn As Boolean = False
            Public Property IPlayed As Boolean
                Get
                    Return m_IPlayed
                End Get
                Set
                    m_IPlayed = Value
                End Set
            End Property
            Private m_IPlayed As Boolean = False
            Public Property Trade_Received As Boolean
                Get
                    Return m_Trade_Received
                End Get
                Set
                    m_Trade_Received = Value
                End Set
            End Property
            Private m_Trade_Received As Boolean = False
    
            Private Sub SortHand()
                Me.PlayerHand = PlayerHand.OrderBy(Function(x) x.Suit).ThenBy(Function(x) x.Value).ToList()
            End Sub
    
            Public Sub ShowHand()
                SortHand()
                For Each card In PlayerHand
                    Debug.Print([Enum].GetName(GetType(CardSuit), card.Suit) + " " + [Enum].GetName(GetType(CardValue), card.Value) + "  ")
                Next
            End Sub
        End Class
    
        Public Class Played
            Public Property Type() As HandType
                Get
                    Return m_Type
                End Get
                Set
                    m_Type = Value
                End Set
            End Property
            Private m_Type As HandType
            Public Property Cards() As List(Of Card)
                Get
                    Return m_Cards
                End Get
                Set
                    m_Cards = Value
                End Set
            End Property
            Private m_Cards As List(Of Card)
    
            Sub New(Optional CardList As List(Of Card) = Nothing, Optional HType As HandType = Nothing)
                m_Type = HType
                m_Cards = CardList
            End Sub
        End Class
    End Namespace

  2. #2
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Custom class varables & multi-threading

    I don't see any code regarding threads in what you posted. And there is no variable named 'Client'. There is a class named 'Client', but that is not a variable.

    So I need to see more code before I can say anything.

    But also beware this:
    Code:
                    Client_Window.PopulateHostCards()
    There are two reasons this line makes me upset.

    The first is Forms don't play well with multiple threads. If the secondary thread can set the HostHand property, you need to do a little bit of work to make sure you do Form-oriented work on the main thread.

    The second is I don't see a variable named 'Client_Window', so I know you're using the default instance of the form. Default instances play ESPECIALLY poorly with threads. Basically every thread gets its own instance, so if this line got called from the secondary thread, a new Client_Window form will be made and you'll operate on THAT, and not the one on the screen.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Jan 2016
    Posts
    216

    Re: Custom class varables & multi-threading

    yes, that is the class i posted (that is used by the variable)

    this is done is done inside a module (not the form)
    Code:
    Public GameData As CardData.Client
    it gets "set" inside a thread (i'm not about to post the whole program) (located in the same module)
    Code:
    GameData = New CardData.Client
    this part is in the "form"
    but you can remove it. as i noted it runs fine, the issue comes later
    Code:
    Client_Window.PopulateHostCards()

    my problem is after the thread is done. when i access "GameData", it's empty. = Nothing.

    does that help?

  4. #4
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Custom class varables & multi-threading

    The best explanation I can come up with, since I can't see your code, is that you have declared a more local variable named GameData that hides the more global one. So you set the local variable but don't set the global one. Here's an example of what that looks like, and yes it's legal:
    Code:
    Module Module1
    
        Private GameData As GameData
    
        Sub Main()
            BadIdea()
            If GameData Is Nothing Then
                Console.WriteLine("Oh no!")
            End If
        End Sub
    
        Private Sub BadIdea()
            Dim GameData As GameData
    
            GameData = New GameData()
        End Sub
    
    End Module
    
    Public Class GameData
    
    End Class
    If that's the case, you can take some measures to not accidentally make the mistake again. Most VB developers follow special rules about how they capitalize their variables to help them understand if they're talking about something global, local, or a parameter. This makes it harder to accidentally access the wrong thing. Here's how I would have written the above:
    Code:
    Module Module1
    
        Private _gameData As GameData
    
        Sub Main()
            BadIdea()
            If _gameData Is Nothing Then
                Console.WriteLine("Oh no!")
            End If
        End Sub
    
        Private Sub BadIdea()
            Dim gameData As New GameData()
            _gameData = gameData
        End Sub
    
    End Module
    
    Public Class GameData
    
    End Class
    In the conventions I use, "_gameData" has an underscore in front to help me remember it's part of the Module. So if I want to touch the module's variable and I didn't type an underscore, I know I did wrong. When I declared the local data, I used the lowercase "gameData" to help me remember it's a variable, not the type. The type is capitalized "GameData" to help me remember that it's "important". This gets a little wonky because I also capitalize properties. Some people follow the rule, "Never name a property the same thing as a class". I find that I don't tend to get as confused about that as I do in the cases that make the underscore needed.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Jan 2016
    Posts
    216

    Re: Custom class varables & multi-threading

    It was a good theory (GameData being set in multiple locations), but it's only ever set (created) once.

    I should clarify one thing (that may help). when i say GameData is empty when i try to access it after the thread runs that sets it, I am referring the the sub values. the GameData variable/object itself does contain all the sub variables, but they are all blank/empty/default states. this is why i think it's something i missed in the class creation code.. (OP), as the sub variables are all set and usable while in the thread. it's only when it exits the thread that they vanish.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width