【问题标题】:cross-thread operation not valid: ContextMenuStrip跨线程操作无效:ContextMenuStrip
【发布时间】:2012-03-16 09:56:07
【问题描述】:

我对“线程”有疑问。我希望有两个在单独的过程中工作的“表单”,例如,如果我从一个“表单”打开一个“OpenFileDialog”,另一个“表单”单独工作并做其他事情。 (请参阅我的代码,我对我的错误描述感到抱歉。)

我使用了一个“线程”,它工作正常。但如果我的“表单”有“ContextMenuStrip”控件,则会出现“跨线程操作无效”错误。 请帮帮我。

谢谢。

================================================ ==================================== 主窗体:

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

================================================ ==================================== 表格2:

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

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

这是我的源代码: http://www.mediafire.com/?m8e8i51rr51a35i [63KB]

运行“FormMain”。 单击“cmdShow”。 当显示“Form2”时。右键单击“面板1”。 'ContextMenuStrip1' 将会出现。

关闭'Form2.

再次单击“cmdShow”。 当显示“Form2”时。再次右键单击“Panel1”。 但你可以看到错误...

【问题讨论】:

  • 你应该把相关代码贴在这里,不要强迫我们去点击未知的外部链接。
  • 同样,我没有下载任何代码来找出问题所在。

标签: vb.net multithreading


【解决方案1】:

你没有在这部分调用

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 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

【讨论】:

  • 这也不起作用,因为我检查了 'ContextMenuStrip1.InvokeRequired=true' 而不是 'Me',当我使用 'ContextMenuStrip1.Invoke(d)' 时,此代码不起作用!跨度>
【解决方案2】:

该错误是因为您尝试从不是 UI 线程(主线程)的线程修改您的 GUI。

在更新 UI 或执行与 UI 相关的任何操作之前,您必须调用任何控件。

考虑以下代码 sn-p :

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 是异步的,Invoke 是同步的

参数是:将被执行的委托,以及最终传递的对象数组。

但是有些事情困扰着我,为什么要让 2 个表单在单独的线程中“工作”?在任何情况下,您都不应该在您的 GUI 中进行任何繁重的处理。

编辑:

好的,所以我明白出了什么问题:您只需要一个非模式对话框! 但是 OpenFileDialog 是模态的(参见C# OpenFileDialog Non-Modal possible) 问题与线程无关!

【讨论】:

  • 抱歉,我不明白你在说什么。你能解释更多吗?如果可能的话,我希望你检查我的源代码。谢谢。
  • 您遇到了线程问题。基本上,不允许修改 UI 的线程正在尝试修改 UI。所以这会导致异常。
  • 你不能。这就是为什么你必须调用允许修改 UI 的线程。
  • 当我使用:'Me.ShowDialog()' 时发生'跨线程',当我使用'If ContextMenuStrip1.InvokeRequired Then Dim d As New dlgShow_View_(AddressOf Show_View_) ContextMenuStrip1.BeginInvoke( d) Else Me.ShowDialog() End If' 此代码无效。
  • 那是因为 OpenFileDialog 是模态的!它与线程无关!
猜你喜欢
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多