我遇到問題,即使看到事件發生,我的主窗體仍未更新。讓我解釋一下我的情況,並分享我的一些代碼,由於我是業餘愛好者,所以我敢肯定這些代碼會很糟糕。在自定義類事件被觸發後,表單不會更新
我創建了一個類來接受在後臺運行進程的設置。我在該類中添加了一些自定義事件,所以我可以在表單中使用它而不是定時器。
爲了處理這些事件,我放了兩個子節點,我發現它們在安裝開始後立即啓動。
我看了一下數據,發現並沒有例外。
起初我以爲這是因爲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中添加了處理程序,並且在form1中添加了它將實際發生的事件,而不是創建新的form1對象。 發生以下代碼的Addlog函數是一個模塊。 Form1.tbLogs.AppendText(s&vbCrLf) 所以當你說我需要傳遞一個對實際表單對象的引用時,我該怎麼做? 昨天我在事件中嘗試過,因爲它的形式是做me.tblogs.appendtext,但它有相同的效果。 – JoshF 2010-09-24 20:37:40
這是一個非常基本的面向對象問題,很難讓你在評論框中加快速度。 Q&D修補程序是使用Application.OpenForms(0)代替,這是對創建的第一個窗體的引用。可能是Form1。 – 2010-09-24 20:43:51
我會試一試,謝謝Hans。這是否解釋了爲什麼它在10秒後顯示在文本框中? 我的意思是如果我正確地讀你,它根本不會更新,因爲它會完全與不同的對象進行交互。 – JoshF 2010-09-24 20:45:07