vb.net 文本框没有变化

vb.net TextBox does not change

我无法从另一个模块更新 TextBox 内容。
TextBox 在名为 frm_main 的表单中,事件处理程序在另一个名为 md_zeiss.

的模块中

Init()frm_main 上的按钮调用。

问题:
如果我直接从 frm_main 调用 Test() 更改文本。
如果由事件调用,它不会更改文本,但会显示正确的 MessageBox。

代码:

Module md_zeiss

Sub Init()

    Dim fsw As New FileSystemWatcher

    fsw.Path = "C:\Output"
    fsw.Filter = "*.txt"
    fsw.NotifyFilter = NotifyFilters.Attributes Or NotifyFilters.CreationTime Or NotifyFilters.DirectoryName _
        Or NotifyFilters.FileName Or NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.Security Or NotifyFilters.Size

    fsw.EnableRaisingEvents = True

    AddHandler fsw.Changed, AddressOf md_zeiss.Main

End Sub

Sub Main(sender As Object, e As IO.FileSystemEventArgs)

    Do While IsLocked(e.FullPath) = True
        Application.DoEvents()
    Loop

    Dim fs As New FileStream(e.FullPath, FileMode.Open, FileAccess.Read)
    Dim sr As New StreamReader(fs, System.Text.Encoding.Default)

    Dim textline As String = vbNullString

    Dim nr As String
    Dim gi As String
    Dim le As String

    Do Until sr.Peek = -1
        textline = sr.ReadLine
        Select Case True
            Case InStr(textline, vbTab & "Ø MOLDING_NR_SIDE" & vbTab)
                nr = ReadVal(textline, 5)
            Case InStr(textline, vbTab & "LENGTH" & vbTab)
                gi = ReadVal(textline, 5)
            Case InStr(textline, vbTab & "Ø MOLDING_GI_SIDE" & vbTab)
                le = ReadVal(textline, 5)
        End Select
    Loop

    Test()

End Sub

Sub Test()

    frm_Main.TextBox1.Text = "Test"
    MsgBox(frm_Main.TextBox1.Text)

End Sub

默认情况下,FileSystemWatcher 在辅助线程上引发事件。表单的默认实例是特定于线程的,因此如果您在 UI 线程上显示表单的默认实例,然后尝试从 FileSystemWatcher 事件的处理程序(或调用的方法)访问默认实例来自那个处理程序)那么你实际上指的是两个不同的表单对象。

最简单的选项是在UI线程上设置FileSystemWatcherSynchronizingObject属性。您可以为该 属性 分配一个表单或其他控件,然后 FileSystemWatcher 将在拥有该控件的线程(即 UI 线程)上引发其事件。如果你确实沿着这条路走下去,只要确保你的事件处理程序被快速执行即可。您不想将 UI 线程与长 运行 代码捆绑在一起,这就是默认使用辅助线程的原因。

另一种选择是在您的模块中使用 SynchronizationContext class 以允许您编组对 UI 线程的方法调用。您将继续让 FileSystemWatcher 在辅助线程上引发其事件并在那里进行后台工作,然后在 SynchronizationContext 上调用 SendPost 以调用方法UI 线程,其中使用该表单的默认实例将引用与您已经显示的相同的实例。

但基本上,那里的建筑很糟糕。您几乎肯定应该使用 class 而不是模块,然后表单可以保留对该 class 实例的引用。然后 class 可以引发表单可以处理的适当事件,然后表单可以更新自己的 TextBox。如果您访问该窗体之外的窗体上的控件,那么代码本质上是错误的。默认表单实例使这件事变得更容易,这是经验丰富的开发人员通常不喜欢它们的原因之一。它们让初学者更容易起床 运行,但当事情变得非常复杂时,它也让初学者更容易把自己逼到墙角。