1,105,225 Community Members

Accessing form controls from another thread

Member Avatar
Minko
Light Poster
29 posts since Jun 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Hello,

How can I go about hiding a form from another thread.

I have two forms and a module, from the module I have started a new thread and at some point during this thread I want to hide the second form. How would I go about this as everything I have tried has not worked so far.

Thanks in advance,

Minko

Member Avatar
Reverend Jim
Noli mentula
5,393 posts since Aug 2010
Reputation Points: 744 [?]
Q&As Helped to Solve: 643 [?]
Skill Endorsements: 51 [?]
Moderator
Featured
 
0
 

I have one suggestion (not necessarily a great one). Set a class variable in the main form (call it something like ShowForm). Set it to True initially. Have a timer on the main form and set the interval to 1000. In the timer Tick event do

Me.Visible = ShowForm

You can modify the value of ShowForm from another thread. The Tick event in the main form will do the actual show/hide. If you need the show/hide to be more reactive then shorten the Interval value.

Member Avatar
Minko
Light Poster
29 posts since Jun 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Ok, thanks for replying. I have already used this method, I was just wandering if there was a better way of doing this?.

Many thanks,

Minko

Member Avatar
TnTinMN
Practically a Master Poster
640 posts since Jun 2012
Reputation Points: 418 [?]
Q&As Helped to Solve: 152 [?]
Skill Endorsements: 16 [?]
 
0
 

I'm not sure I understand your situation correctly, but UI controls must be manipulated only on the thread that created them. Here is an example that flashes Form2. Note the pattern used with the InvokeRequired.

Public Class Form1
   Private WithEvents bgw As New System.ComponentModel.BackgroundWorker With {.WorkerSupportsCancellation = True}

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      bgw.RunWorkerAsync()
   End Sub

   Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
      bgw.CancelAsync() ' cancel backgroundworker
   End Sub

   Private Sub ToggleForm2()
      If Me.InvokeRequired Then
         ' on other thread so call on UI thread
         Me.Invoke(New MethodInvoker(AddressOf ToggleForm2))
         Exit Sub ' on non UI thread
      End If

      Form2.Visible = Not Form2.Visible

   End Sub

   Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
      Do
         If bgw.CancellationPending Then
            e.Cancel = True
            Exit Do
         End If
         ToggleForm2()
         Threading.Thread.Sleep(1000)
      Loop
   End Sub

End Class
Member Avatar
Minko
Light Poster
29 posts since Jun 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

@TnTinMN Thanks, for replying. However I have already tried this method and it did not work for me. The thread is running in a module so I can not use me.invoke so I tried to do form1.invoke but it errors saying the handle has not been created. Also just to note if I do form1.invokeRequired it returns false but still does not hide the form.

At the moment I think I will go ahead and use what Reverend Jim said. However if anybody else has a better solution then please do say.

Many thanks to both of you,

Minko

Member Avatar
tinstaafl
Postaholic
2,009 posts since Jun 2010
Reputation Points: 559 [?]
Q&As Helped to Solve: 400 [?]
Skill Endorsements: 35 [?]
 
0
 

one other thing to try, is when you call the routine in the module, pass the Form1.Handle as a parameter. You should be able to control it then.

Member Avatar
TnTinMN
Practically a Master Poster
640 posts since Jun 2012
Reputation Points: 418 [?]
Q&As Helped to Solve: 152 [?]
Skill Endorsements: 16 [?]
 
0
 

If by "The thread is running in a module" you mean that the method being executed is in a Module, a similar technique can be used. Here is a slightly different version executing a method defined in a module.

Public Class Form1

   Private myParameterInstance As MyParameter
   Dim thrd As Threading.Thread

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      thrd = New Threading.Thread(AddressOf Something.threadMethod)
      myParameterInstance = New MyParameter(New MethodInvoker(AddressOf ToggleForm2))
      thrd.Start(myParameterInstance)
   End Sub

   Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
      myParameterInstance.Cancel = True
   End Sub

   Private Sub ToggleForm2()
      If Me.InvokeRequired Then
         ' on other thread so call on UI thread
         Me.Invoke(New MethodInvoker(AddressOf ToggleForm2))
         Exit Sub ' on non UI thread
      End If
      Form2.Visible = Not Form2.Visible
   End Sub

   Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
      ' Clean up
      If myParameterInstance IsNot Nothing Then
         myParameterInstance.Cancel = True 'shut the thread down
         While thrd.IsAlive
            Threading.Thread.Sleep(500)
            Debug.WriteLine("waiting to end")
         End While
      End If
   End Sub
End Class

' Define a parameter class that contains the info to be passed to the threaded method
' You could just pass a MethodInvoker instance, but I like having a way to cancel a thread
' so I use a Class with a Cancel Property
Friend Class MyParameter

   Public mi As MethodInvoker 'use a simple MethodInvoker to execute a UI method
   Public Sub New(ByVal mi As MethodInvoker)
      Me.mi = mi
   End Sub

   Private _Cancel As Boolean
   Public Property Cancel() As Boolean
      Get
         Return _Cancel
      End Get
      Set(ByVal value As Boolean)
         _Cancel = value
      End Set
   End Property 'Cancel
End Class

Module Something
   Sub threadMethod(ByVal parameter As Object)
      ' the parameter must be passed as an Object
      ' convert it to an instance of MyParameter
      Dim param As MyParameter = CType(parameter, MyParameter)

      Do Until param.Cancel
         param.mi.Invoke()
         Threading.Thread.Sleep(2500)
      Loop
   End Sub
End Module
Member Avatar
Minko
Light Poster
29 posts since Jun 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Thank you to everybody for helping. I have managed to sort my problem out so I will mark this as solved. once again thanks to everyone who helped.

Kindest Regards,

Minko

Question Answered as of 1 Year Ago by TnTinMN, tinstaafl and Reverend Jim
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article