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

Recommended Answers

All 7 Replies

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.

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

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

@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

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.

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

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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.