0

I have a problem with 'Threading'. I want to have two 'form' that work in separate process, for example if i open a 'OpenFileDialog' from one 'form', the other 'form' works separately and do some things else. (see my code, I'm surry for my bad description.)

I used a 'Thread' and it's work fine. but if my 'form' has 'ContextMenuStrip' control, error 'cross-thread operation not valid' occurred. Please help me.

thanks.

================================================================================= FormMain:

Public Class FormMain

Private Sub cmdShow_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdShow.Click
    Form2.ShowMe()
End Sub

End Class

================================================================================= Form2:

Public Class Form2

'Me.ContextMenuStrip1 = New System.Windows.Forms.ContextMenuStrip(Me.components)
'Me.Panel1 = New System.Windows.Forms.Panel
'Me.Panel1.ContextMenuStrip = Me.ContextMenuStrip1


Public Shared Thread_2 As System.Threading.Thread
Public MyDefaultWindowState = FormWindowState.Normal

Private Delegate Sub dlgShowMe()
Public Sub ShowMe()
    If Thread_2 IsNot Nothing AndAlso Thread_2.ThreadState = Threading.ThreadState.Running Then
        If Me.InvokeRequired Then
            Dim d As New dlgShowMe(AddressOf Me.ShowMe)
            Me.Invoke(d)
        Else
            Show_Activate_()
        End If
    Else
        Thread_2 = New System.Threading.Thread(AddressOf Me.Show_View_)
        Thread_2.SetApartmentState(System.Threading.ApartmentState.STA)
        Thread_2.IsBackground = False
        Thread_2.Start()
    End If
End Sub

Private Sub Show_Activate_()
    Try
        Me.Enabled = True
        Me.ShowInTaskbar = True
        Me.WindowState = Me.MyDefaultWindowState

        Me.BringToFront()
        Me.Activate()
    Catch ex As Exception
        MsgBox(ex.Message, , "Show_Activate_")
    End Try
End Sub
Private Delegate Sub dlgShow_View_()
Private Sub Show_View_()
    Me.Enabled = True
    Me.ShowInTaskbar = True

    Try
        Me.ShowDialog()
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Critical,"Show_View_")
    End Try
End Sub


Private Sub cmdOpenFileDialog1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenFileDialog1.Click
    OpenFileDialog1.ShowDialog()
End Sub

End Class

================================================

here is my source code: http://www.mediafire.com/?m8e8i51rr51a35i [63KB]

Run 'FormMain'. click 'cmdShow'. when 'Form2' shown. right click on 'Panel1'. 'ContextMenuStrip1' will be appeared.

close 'Form2.

click 'cmdShow' again. when 'Form2' shown. right click on 'Panel1' again. but you can see error...

mohammad azadi
  • 306
  • 4
  • 13

2 Answers2

0

The error is because you are trying to modify your GUI from a thread that isnt the UI thread (main thread).

You will have to invoke on any control before updating the UI or doing anything related to the UI.

Consider the following code snippet :

Friend Shared Sub RaiseUiEvent(ByVal hnd As EventHandler, ByVal sender As Object, ByVal e As EventArgs)
    Dim uiRef = GlobalManager.GetInstance().UI 'uiRef is just a ref to a control of my UI

    uiRef.BeginInvoke(hnd, sender, e)     
End Sub

BeginInvoke is async, Invoke is sync

The params are : a delegate that will be executed, and eventually an array of objects that are passed.

But something is bothering me, why do you want to have 2 forms "working" in separate threads ? You shouldnt have any heavy processing in your GUI in any case.

Edit :

ok so I understand what is wrong : you simply want a Non modal dialog box ! But the OpenFileDialog is modal (cf C# OpenFileDialog Non-Modal possible) The problem has nothing to do with threads !

Community
  • 1
  • 1
squelos
  • 1,189
  • 6
  • 16
  • surry, i dont understand what you say. can you explain more? i want you check my source code, if possible. thanks. – mohammad azadi Mar 16 '12 at 12:54
  • You are having a threading issue. Basically, a thread that isnt allowed to modify the UI is trying to modify the UI. So that causes an exception. – squelos Mar 16 '12 at 12:55
  • You cant. Thats why you have to invoke onto the thread that is allowed to modify the UI. – squelos Mar 16 '12 at 13:29
  • when i useing: 'Me.ShowDialog()' the 'cross-thread' occurred, and when i useing 'If ContextMenuStrip1.InvokeRequired Then Dim d As New dlgShow_View_(AddressOf Show_View_) ContextMenuStrip1.BeginInvoke(d) Else Me.ShowDialog() End If' this code is not work. – mohammad azadi Mar 16 '12 at 13:36
  • Im just after reading your code. Just get rid of that second thread. Its pointless. There is no need for threading here, and you are using a lot of complicated things for nothing at all here. Edit you should probably be using an invoke on that showdialog ! thats what is causing the issue from what i see here. – squelos Mar 16 '12 at 13:37
  • in this code, yes. but i want to have 2 forms with a 'button' and a 'ContextMenuStrip1' on each others that 'button' open a 'OpenFileDialog' and 'ContextMenuStrip1' do some things, when click on 'button1' of 'Form1' to open a 'OpenFileDialog', i cannot access to 'Form2' such move,click,... it. so i use thread. but i have problem with thread. plz help me. thanks. – mohammad azadi Mar 16 '12 at 13:45
  • 1
    Thats because the OpenFileDialog is modal ! It has nothing to do with threads ! – squelos Mar 16 '12 at 14:05
0

You are not invoking in this part

Private Delegate Sub dlgShow_View_()
Private Sub Show_View_()
    Me.Enabled = True
    Me.ShowInTaskbar = True

    Try
        Me.ShowDialog()
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Critical,"Show_View_")
    End Try
End Sub

you should change it to :

Private Delegate Sub dlgShow_View_()
Private Sub Show_View_()
    if Me.InvokeRequired Then
        Dim d as New dlgShow_View_(adressOf Show_View_)
    else
    Me.Enabled = True
    Me.ShowInTaskbar = True

    Try
        Me.ShowDialog()
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Critical,"Show_View_")
    End Try
    End If
End Sub
jasperagrante
  • 354
  • 4
  • 17
  • this is not work too, because i check that 'ContextMenuStrip1.InvokeRequired=true' not 'Me', and when i use 'ContextMenuStrip1.Invoke(d)' then this code not work! – mohammad azadi Mar 16 '12 at 13:56