vb.net形成冻结,​​线程,事件和混乱的菜鸟

时间:2016-12-28 10:29:27

标签: vb.net forms events thread-safety

从事件加载表单时,我遇到了冻结表单的问题。我打赌它与线程有关,但遗憾的是我自己也不太了解它:(

让我解释一下我的项目: 我有一个连接到网络事件的课程(例如新连接), 我已经在一个表单中实例化并从中声明了一些事件。

Public Netstat As New aaNetTool.clsNetworkStatus  

AddHandler Netstat.NetworkChanged, AddressOf Network_Changed

Sub Network_Changed()

End Sub

然后我写了另一个类clsMessage,我想用它来显示带通知的表单。

Public Class clsMessage
    Private myForm As frmDisplayMessage

    Public Sub New(ByVal Title$, ByVal Text$, Optional btnYesAction As Action = Nothing, Optional ByVal ShowTimeSec% = 10)
        myForm = New frmDisplayMessage
        myForm.Text = Title
        myForm.lblText.Text = Text
        (...)
        myForm.Show()
        (...)
    End Sub

现在我使用主窗体中的按钮创建一个用于调试目的的新通知窗口,如下所示:

Dim myMsg As New clsMessage("title", "text", AddressOf MapNetworkdrives, 30)

这就像一个魅力。

但是当我从宣布的事件中调用通知时:

Sub Network_Changed()
         Dim myMsg As New clsMessage("title", "text", AddressOf MapNetworkdrives, 30)
End Sub

带有通知的表单会显示但是为空且已冻结。 如前所述,我认为这可能与我在不同线程上运行的代码有关,但我无法弄清楚如何解决这个问题:(

提前感谢你的时间,

Lunex

1 个答案:

答案 0 :(得分:1)

clsNetworkStatus.NetworkChanged事件似乎是从后台线程引发的。由于您的通知表单是UI的一部分,因此您必须调用它以便在UI线程下执行。

InvokeRequired property告诉您是否需要调用,因此,如果False您的代码已在UI线程上运行。

您可以创建一个扩展方法来为您进行检查:

Imports System.Runtime.CompilerServices

Public Module Extensions
    <Extension()> _
    Public Sub InvokeIfRequired(ByVal Control As Control, ByVal Method As Action)
        If Control.InvokeRequired = True Then
            Control.Invoke(Method) 'Invoke the method thread-safely.
        Else
            Method.Invoke() 'Call the method normally (equal to just calling: 'Method()').
        End If
    End Sub
End Module

然后你就像这样使用它:

Sub Network_Changed()
     Me.InvokeIfRequired(Sub()
                                           Dim myMsg As New clsMessage("title", "text", AddressOf MapNetworkdrives, 30)
                                       End Sub)
End Sub