我有一个系统托盘应用程序。托盘应用程序有一个图标和一些带有选项的上下文菜单。有一个名为status的菜单,其中包含以下toolstripmenuitems:
根据某些条件启用/禁用它们。
我的系统托盘应用程序,后台线程确实不断检查某些条件并做一些工作。它的主要循环如下:
Do Until gAppExit Or Me.thdExit
' Check some conditions and do some work
Loop
gAppExit是一个全局变量,用于指示用户是否已通过“退出”工具线程设备退出应用程序。
thdExit指示线程是否应该从循环中退出(我稍后会解释)。
当用户想要重新启动后台线程时,他点击了restart toolstripmenuitem并完成了以下序列(Restart - > Halt - > WaitFinish):
Public Function ReStart() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Logger.Write("Task is not yet created!", LOGGING_CRITICAL_ERRORS_CATEGORY)
Return RESULT_ERROR
End If
result = Me.Halt()
If result <> RESULT_ERROR Then
result = Me.Start()
End If
Return result
End Function
Public Function Halt() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Logger.Write("Task is not yet created!", LOGGING_CRITICAL_ERRORS_CATEGORY)
Return RESULT_ERROR
End If
Me.thdExit = True
result = Me.WaitFinish()
Return result
End Function
Public Function WaitFinish() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Return RESULT_ERROR
End If
result = RESULT_ERROR
Try
'TODO:
Console.WriteLine("Wait thread to finish (before Join)...")
Me.ThreadBgWorker.Join()
'TODO:
Console.WriteLine("Thread finished... Continue restarting thread...")
Me.RetVal = True
result = Me.ThreadBgWorker.ManagedThreadId
Logger.Write(String.Format("Task ""{0}"" correctly stopped.", _
Me.ThreadBgWorker.Name))
Catch ex As Exception
Logger.Write(String.Format("Couldn't stop task ""{0}"": {1}", _
Me.ThreadBgWorker.Name, ex.Message), _
LOGGING_CRITICAL_ERRORS_CATEGORY)
End Try
Return result
End Function
Public Function Start() As Integer
Dim result As Integer
If IsNothing(ThreadBgWorker) Then
Logger.Write("Task is not yet created!", LOGGING_CRITICAL_ERRORS_CATEGORY)
Return RESULT_ERROR
End If
result = RESULT_ERROR
Me.thdExit = False
Try
If Me.ThreadBgWorker.ThreadState = Threading.ThreadState.Stopped Then
Me.Create()
End If
Me.ThreadBgWorker.Start() ' Start the new thread.
result = Me.ThreadBgWorker.ManagedThreadId
Logger.Write(String.Format("Task ""{0}"" correctly started.", _
Me.ThreadBgWorker.Name))
Catch ex As Exception
Logger.Write(String.Format("Couldn't start task ""{0}"": {1}", _
Me.ThreadBgWorker.Name, ex.Message), _
LOGGING_CRITICAL_ERRORS_CATEGORY)
End Try
Return result
End Function
请注意,在Halt函数上,它等待线程完成,方法是在函数WaitFinish上调用Me.ThreadBgWorker.Join()。在调用WaitFinish函数之前,thdExit设置为true以便后台线程可以从主循环中退出:
Do Until gAppExit Or Me.thdExit
' Check some conditions and do some work
Loop
ChangeStatusToStopped()
退出循环,调用ChangeStatusToStopped(),如下所示:
Private Delegate Sub ChangeStatusToStoppedDelegate()
Public Sub ChangeStatusToStopped()
' TODO:
Console.WriteLine("Changing status to stopped...")
System.Windows.Forms.Application.DoEvents()
If MainMenu.InvokeRequired Then
'TODO:
Console.WriteLine("Invoke required!")
MainMenu.Invoke(New ChangeStatusToStoppedDelegate(AddressOf ChangeStatusToStopped))
Else
'TODO:
Console.WriteLine("Invoke NOT required!")
Me.submnuStart.Enabled = True
Me.submnuReStart.Enabled = False
Me.submnuStop.Enabled = False
End If
' TODO:
Console.WriteLine("Status changed to stopped.")
End Sub
它的作用是在UI中启用启动toolstripmenuitem并禁用restart并停止toolstripmenuitems。
问题是:
在ChangeStatusToStopped方法中,当MainMenu.InvokeRequired为true时,它调用:
MainMenu.Invoke(New ChangeStatusToStoppedDelegate(AddressOf ChangeStatusToStopped))
然后它卡在那里,也就是身体:
Me.submnuStart.Enabled = True
Me.submnuReStart.Enabled = False
Me.submnuStop.Enabled = False
永远不会执行。好像主线程正忙或消息泵中的其他问题......有什么想法吗?
我看过那行:
Me.ThreadBgWorker.Join()
在后台线程退出主循环之前已达到WaitFinish()函数中的,并且在执行Me.ThreadBgWorker.Join()之前已将thdExit设置为true,一旦执行了连接,应用程序就会卡住,后台线程无法退出主循环(似乎应用程序正在忙碌或冻结。)