gpt4 book ai didi

vb.net - 触发自定义类事件后,表单未更新

转载 作者:行者123 更新时间:2023-12-01 15:30:01 25 4
gpt4 key购买 nike

我遇到了一个问题,即即使我看到事件已触发,我的主表单也没有更新。让我解释一下情况并分享我的一些代码,我相信这些代码会很糟糕,因为我是一个业余爱好者。

我创建了一个类来接收在后台运行进程的设置。我在那个类中添加了一些自定义事件,这样我就可以在我的表单中使用它而不是计时器。

我中断了处理这些事件的两个子程序,我看到它们在安装开始后立即启动。

我查看了数据,它正在处理,没有抛出任何异常。

起初我以为是因为datagridview有一些延迟问题。我通过我发现的一些技巧将其设置为双缓冲,但这并不重要。在数据显示在数据网格中之前,仍有大约 10 秒的延迟。

我想了想并决定我真的不需要 datagridview 并将控件替换为多行文本框,但这并没有什么不同。显示对表单/文本框的更新仍需要 10 秒或更长时间。

我在下面包含了我的一些代码。

Public Shared WithEvents np As NewProcess

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
np = New NewProcess
AddHandler np.InstallFinished, AddressOf np_InstallFinished
AddHandler np.InstallStarted, AddressOf np_InstallStarted
Catch ex As Exception

End Try

End Sub

Protected Sub np_InstallFinished(ByVal Description As String, ByVal ExitCode As Integer)
InstallInProcess = False

If Not Description = Nothing Then
If Not ExitCode = Nothing Then
AddLog(String.Format("Completed install of {0} ({1}).", Description, ExitCode))
Else
AddLog(String.Format("Completed install of {0}.", Description))
End If
End If
RefreshButtons()
UpdateListofApps()
np.Dispose()
End Sub

Protected Sub np_InstallStarted(ByVal Description As String)
InstallInProcess = True

If Not Description = Nothing Then AddLog(String.Format("Started the install of {0}.", Description))
End Sub

Public Class NewProcess
Dim ProcessName As String
Dim ProcessVisibile As Boolean
Dim Arguments As String
Dim WaitforExit As Boolean
Dim Description As String
Dim ShellExecute As Boolean
Dim EC As Integer = Nothing 'Exit Code
Private IsBusy As Boolean = Nothing
Dim th As Threading.Thread

Public Event InstallFinished(ByVal Description As String, ByVal ExitCode As Integer)

Public Event InstallStarted(ByVal Description As String)

Public Function Busy() As Boolean
If IsBusy = Nothing Then Return False
Return IsBusy
End Function

Public Function ExitCode() As Integer
Return EC
End Function

Public Function ProcessDescription() As String
Return Description
End Function

''' <summary>
''' Starts a new multithreaded process.
''' </summary>
''' <param name="path">Path of the File to run</param>
''' <param name="Visible">Should application be visible?</param>
''' <param name="Arg">Arguments</param>
''' <param name="WaitforExit">Wait for application to exit?</param>
''' <param name="Description">Description that will show up in logs</param>
''' <remarks>Starts a new multithreaded process.</remarks>
Public Sub StartProcess(ByVal path As String, ByVal Visible As Boolean, Optional ByVal Arg As String = Nothing, Optional ByVal WaitforExit As Boolean = False, Optional ByVal Description As String = Nothing)

Try
Me.ProcessName = path
Me.ProcessVisibile = Visible
If Arguments = Nothing Then Me.Arguments = Arg
Me.Description = Description
Me.WaitforExit = WaitforExit

If IsBusy And WaitforExit Then
MessageBox.Show("Another install is already in process, please wait for previous install to finish.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Exit Sub
End If

If Not fn_FileExists(ProcessName) Then
MessageBox.Show("Could not find file " & ProcessName & ".", "Could not start process because file is missing.", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If

th = New Threading.Thread(AddressOf NewThread)

With th
.IsBackground = True
If Not Description Is Nothing Then .Name = Description
.Start()
End With
Catch ex As Exception

End Try
End Sub

Private Sub NewThread()
Dim p As Process

Try
p = New Process

With p
.EnableRaisingEvents = True
.StartInfo.Arguments = Arguments
.StartInfo.FileName = ProcessName
.StartInfo.CreateNoWindow = ProcessVisibile
End With

If ProcessVisibile Then
p.StartInfo.WindowStyle = ProcessWindowStyle.Normal
Else
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
End If

p.Start()
IsBusy = True
RaiseEvent InstallStarted(Description)

If WaitforExit Then
Do While p.HasExited = False
Threading.Thread.Sleep(500)
Loop
IsBusy = False
RaiseEvent InstallFinished(Description, p.ExitCode)
End If

EC = p.ExitCode

Catch ex As Exception

End Try
End Sub

Public Sub Dispose()
ProcessName = Nothing
ProcessVisibile = Nothing
Arguments = Nothing
WaitforExit = Nothing
Description = Nothing
EC = Nothing
InstallInProcess = Nothing
th.Join()
MemoryManagement.FlushMemory()
End Sub

End Class

Sub AddLog(ByVal s As String)
Try

s = String.Format("[{0}] {1}", TimeOfDay.ToShortTimeString, s)

Form1.tbLogs.AppendText(s & vbCrLf)

Using st As New StreamWriter(LogFilePath, True)
st.WriteLine(s)
st.Flush()
End Using

Catch ex As Exception
End Try
End Sub

有什么想法吗?我完全不知所措。

我已经尝试添加 application.doevents、me.refresh 和其他一些东西 :(

最佳答案

    Form1.tbLogs.AppendText(s & vbCrLf)

标准 VB.NET 陷阱。 Form1 是一个类名,而不是对表单的引用。不幸的是,VB.NET 从合法的 VB6 中实现了一个过时的错误。但是,当您使用线程时它会分崩离析。您将获得自动创建的另一个 表单对象,该对象是不可见的,因为它的 Show() 方法从未被调用过。否则就死定了,因为线程没有启动消息循环。

您需要将对用户正在查看的实际表单对象的引用传递给工作类。 Form1 代码中 Me 的值。您还必须使用 Control.Invoke,因为从另一个线程更新控件是不合法的。我建议您改为触发一个事件,一个 Form1 可以订阅的事件,这样您的工作类就不会被 UI 的实现细节感染。

关于vb.net - 触发自定义类事件后,表单未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3790574/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com