Accessing a form from a thread running on a second form

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Wagz
    New Member
    • Feb 2008
    • 11

    Accessing a form from a thread running on a second form

    Hi,

    I have a main form which starts up a thread as well as a 2nd form.

    How do I make it so that I can access things such as labels on the 2nd form from the thread that was started on form1?

    I have some sample code below...
    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Form2.Show()
            Form2.BringToFront()
            signal = New Class1
        End Sub
        Private signal As Class1
    
    End Class
    
    
    Public Class Class1
        Public Sub New()
            trd = New Threading.Thread(AddressOf task)
            trd.IsBackground = True
            trd.Start()
        End Sub
        Private trd As Threading.Thread
        Private Sub task()
            For i As Integer = 0 To 5
                Threading.Thread.Sleep(5000)
                Form2.Label1.Text = i.ToString
            Next
        End Sub
    End Class
    Any help would be much appreciated.

    Thanks,

    Wagz
  • Shashi Sadasivan
    Recognized Expert Top Contributor
    • Aug 2007
    • 1435

    #2
    have you tried passing the instance of Form1 to both Form2 and signal ?

    Comment

    • Wagz
      New Member
      • Feb 2008
      • 11

      #3
      It appears that every time I'm in the created thread and call something from form2 that it creates a new instance of the form. How do I reference the form that form1 created from the created thread?

      Comment

      • jjvainav
        New Member
        • Feb 2008
        • 25

        #4
        The best approach to this would be to create an event in Class1 that gets raised whenever you want to indicate progress from your thread.

        Code:
                For i As Integer = 0 To 5
                    Threading.Thread.Sleep(5000)
                    ' Form2.Label1.Text = i.ToString
                    ' singal event here
                Next
        Then from your Form1 class you can handle the event and then set your label for form2

        Code:
        Private Sub SomeEventHandler
           ' If Me.InvokeRequired
           ' Me.Invoke(new EventHandler(SomeEventHandler))
           ' End If
           '
           ' Set label for Form2
        End Sub
        Note that you need to invoke back to the main thread in order to set the label for Form2.

        I hope this helps, it is pseudo code but should hopefully explain what you need to do.

        Originally posted by Wagz
        Hi,

        I have a main form which starts up a thread as well as a 2nd form.

        How do I make it so that I can access things such as labels on the 2nd form from the thread that was started on form1?

        I have some sample code below...
        Code:
        Public Class Form1
        
            Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
                Form2.Show()
                Form2.BringToFront()
                signal = New Class1
            End Sub
            Private signal As Class1
        
        End Class
        
        
        Public Class Class1
            Public Sub New()
                trd = New Threading.Thread(AddressOf task)
                trd.IsBackground = True
                trd.Start()
            End Sub
            Private trd As Threading.Thread
            Private Sub task()
                For i As Integer = 0 To 5
                    Threading.Thread.Sleep(5000)
                    Form2.Label1.Text = i.ToString
                Next
            End Sub
        End Class
        Any help would be much appreciated.

        Thanks,

        Wagz

        Comment

        • Wagz
          New Member
          • Feb 2008
          • 11

          #5
          If I pass Form2 to Class1 when I create it and create a delegate to handle the changing the text then it works.

          I passed it in to Class1 in the constructor, is there a better way to do this? In the future I'd like to be able to possibly add additional forms and therefore don't necessarily want to have to have to modify the class every time I create a new form.

          Below is the code I used:

          Code:
          Public Class Class1
              Public Sub New(ByVal Form2)
                  trd = New Threading.Thread(AddressOf task)
                  trd.IsBackground = True
                  trd.Start()
                  Me.Form2 = Form2
              End Sub
              Private Form2 As Form2
              Private trd As Threading.Thread
              Delegate Sub SetText(ByVal label As Windows.Forms.Label, ByVal text As String)
              Private Sub task()
                  For i As Integer = 0 To 5
                      Threading.Thread.Sleep(5000)
                      Dim DelSetText As SetText = New SetText(AddressOf Form2.SetText)
                      Form2.Invoke(DelSetText, New Object(1) {Form2.Label1, i.ToString})
                  Next
              End Sub
          End Class
          
          Public Class Form1
          
              Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
                  Form2.Show()
                  Form2.BringToFront()
                  signal = New Class1(Form2)
              End Sub
              Private signal As Class1
          
          End Class
          
          Public Class Form2
              Public Sub SetText(ByVal label As Windows.Forms.Label, ByVal item As String)
                  label.Text = item
              End Sub
          End Class

          Comment

          • Wagz
            New Member
            • Feb 2008
            • 11

            #6
            jjvainav, I couldn't get your method to work.

            I raised the event in Class1 and handled it in Form1, but when I go to change the text in Form2 it creates a new instance of Form2.

            Code:
            Public Class Form1
                Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
                    Form2.Show()
                    Form2.BringToFront()
                    signal = New Class1()
                End Sub
                Private WithEvents signal As Class1
                Public Sub SetForm2Text(ByVal text As String) Handles signal.SetText
                    Form2.Label1.Text = text
                End Sub
            End Class
            
            Public Class Class1
                Public Sub New()
                    trd = New Threading.Thread(AddressOf task)
                    trd.IsBackground = True
                    trd.Start()
                End Sub
                Public Event SetText(ByVal text As String)
                Private trd As Threading.Thread
                Private Sub task()
                    For i As Integer = 0 To 5
                        Threading.Thread.Sleep(5000)
                        RaiseEvent SetText(i.ToString)
                    Next
                End Sub
            End Class

            Comment

            • jjvainav
              New Member
              • Feb 2008
              • 25

              #7
              Try this:

              Code:
              Public Class Form1
                  Private Delegate Sub SetTextCallback(ByVal text As String)
              
                  Private form2 As Form2
              
                  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
                      form2 = New Form2
                      form2.Show()
                      form2.BringToFront()
                      signal = New Class1()
                  End Sub
                  Private WithEvents signal As Class1
                  Public Sub SetForm2Text(ByVal text As String) Handles signal.SetText
                      If Me.InvokeRequired Then
                          Me.Invoke(New SetTextCallback(AddressOf SetForm2Text), text)
                      End If
              
                      form2.Label1.Text = text
                  End Sub
              End Class
              
              Public Class Class1
                  Public Sub New()
                      trd = New Threading.Thread(AddressOf task)
                      trd.IsBackground = True
                      trd.Start()
                  End Sub
                  Public Event SetText(ByVal text As String)
                  Private trd As Threading.Thread
                  Private Sub task()
                      For i As Integer = 0 To 5
                          Threading.Thread.Sleep(1000)
                          RaiseEvent SetText(i.ToString)
                      Next
                  End Sub
              End Class
              Originally posted by Wagz
              jjvainav, I couldn't get your method to work.

              I raised the event in Class1 and handled it in Form1, but when I go to change the text in Form2 it creates a new instance of Form2.

              Code:
              Public Class Form1
                  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
                      Form2.Show()
                      Form2.BringToFront()
                      signal = New Class1()
                  End Sub
                  Private WithEvents signal As Class1
                  Public Sub SetForm2Text(ByVal text As String) Handles signal.SetText
                      Form2.Label1.Text = text
                  End Sub
              End Class
              
              Public Class Class1
                  Public Sub New()
                      trd = New Threading.Thread(AddressOf task)
                      trd.IsBackground = True
                      trd.Start()
                  End Sub
                  Public Event SetText(ByVal text As String)
                  Private trd As Threading.Thread
                  Private Sub task()
                      For i As Integer = 0 To 5
                          Threading.Thread.Sleep(5000)
                          RaiseEvent SetText(i.ToString)
                      Next
                  End Sub
              End Class

              Comment

              • Shashi Sadasivan
                Recognized Expert Top Contributor
                • Aug 2007
                • 1435

                #8
                All forms that you create inheri the base class Form.

                If you can identify which forms will be sent (like you send Form1) to Class1
                Also identify the methods that these forms will have in common,

                Put them all into an interface, and pass the instance of the Form as the interface type you just created.

                This way, you will only need to pull the interface type, and call the method, which will do the trick for you

                Comment

                Working...