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线程上设置FileSystemWatcher
的SynchronizingObject
属性。您可以为该 属性 分配一个表单或其他控件,然后 FileSystemWatcher
将在拥有该控件的线程(即 UI 线程)上引发其事件。如果你确实沿着这条路走下去,只要确保你的事件处理程序被快速执行即可。您不想将 UI 线程与长 运行 代码捆绑在一起,这就是默认使用辅助线程的原因。
另一种选择是在您的模块中使用 SynchronizationContext
class 以允许您编组对 UI 线程的方法调用。您将继续让 FileSystemWatcher
在辅助线程上引发其事件并在那里进行后台工作,然后在 SynchronizationContext
上调用 Send
或 Post
以调用方法UI 线程,其中使用该表单的默认实例将引用与您已经显示的相同的实例。
但基本上,那里的建筑很糟糕。您几乎肯定应该使用 class 而不是模块,然后表单可以保留对该 class 实例的引用。然后 class 可以引发表单可以处理的适当事件,然后表单可以更新自己的 TextBox
。如果您访问该窗体之外的窗体上的控件,那么代码本质上是错误的。默认表单实例使这件事变得更容易,这是经验丰富的开发人员通常不喜欢它们的原因之一。它们让初学者更容易起床 运行,但当事情变得非常复杂时,它也让初学者更容易把自己逼到墙角。
我无法从另一个模块更新 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线程上设置FileSystemWatcher
的SynchronizingObject
属性。您可以为该 属性 分配一个表单或其他控件,然后 FileSystemWatcher
将在拥有该控件的线程(即 UI 线程)上引发其事件。如果你确实沿着这条路走下去,只要确保你的事件处理程序被快速执行即可。您不想将 UI 线程与长 运行 代码捆绑在一起,这就是默认使用辅助线程的原因。
另一种选择是在您的模块中使用 SynchronizationContext
class 以允许您编组对 UI 线程的方法调用。您将继续让 FileSystemWatcher
在辅助线程上引发其事件并在那里进行后台工作,然后在 SynchronizationContext
上调用 Send
或 Post
以调用方法UI 线程,其中使用该表单的默认实例将引用与您已经显示的相同的实例。
但基本上,那里的建筑很糟糕。您几乎肯定应该使用 class 而不是模块,然后表单可以保留对该 class 实例的引用。然后 class 可以引发表单可以处理的适当事件,然后表单可以更新自己的 TextBox
。如果您访问该窗体之外的窗体上的控件,那么代码本质上是错误的。默认表单实例使这件事变得更容易,这是经验丰富的开发人员通常不喜欢它们的原因之一。它们让初学者更容易起床 运行,但当事情变得非常复杂时,它也让初学者更容易把自己逼到墙角。