从事件加载表单时,我遇到了冻结表单的问题。我打赌它与线程有关,但遗憾的是我自己也不太了解它:(
让我解释一下我的项目: 我有一个连接到网络事件的课程(例如新连接), 我已经在一个表单中实例化并从中声明了一些事件。
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
答案 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