在winform程序中使用后台工作程序。还与某些设备通信
我有一个停止按钮,试图停止后台工作线程,这有效,但有时,后台工作线程仍处于“已中止”状态
我必须提一下,我关注上升的异常,并使用'Finally'块来停止与设备的通信
我需要立即停止线程,比如紧急按钮......
一些代码:
Private Sub BtnStopTest_Click(sender As Object, e As EventArgs) Handles btnStopTest.Click
Try
stoppedTesting = True
Log("Stopping operations safely. (You might have to wait some time )", Color.Blue, New Font("Microsoft Sans Serif", 9, FontStyle.Bold))
If bgWorkThread IsNot Nothing Then
'stop thread
'if thread is sleeping (waiting for a time)
If bgWorkThread.ThreadState = ThreadState.Background + ThreadState.WaitSleepJoin Then
bgWorkThread.Interrupt()
Else 'if thread is working normally
bgWorker.CancelAsync()
tEO.DoWorkEventArgs.cancel = True
bgWorkThread.Abort()
'sometimes, here the Thread has state 'Aborted
End If
ElseIf bgWorkThread Is Nothing Then
Dim ee As New System.ComponentModel.RunWorkerCompletedEventArgs(New Object, Nothing, False)
BgWorker_RunWorkerCompleted(New Object, ee)
End If
Catch ex As Exception
Utils.PreserveStackTrace(ex)
Log("Error when stopping testing" & vbCrLf & Utils.ReadException(ex), MessageType.ErrorMessage)
End Try
End Sub
Private Sub BgWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgWorker.DoWork
Try
'some other things to do
For Each testStep In stepList
Try
'main operations and communication with device
' below functions are all different
'something like:
'CommunicationWithDevice1()
'CommunicationWithDevice2()
'CommunicationWithDevice3()
'CommunicationWithDevice4()
'....
'CommunicationWithDevice20()
Catch ex As Exception When TypeOf ex Is ThreadAbortException OrElse TypeOf ex Is ThreadInterruptedException
Utils.PreserveStackTrace(ex)
Log("Exception in thread" & vbCrLf & Utils.ReadException(ex), MessageType.ErrorMessage)
e.Cancel = True
If ex.GetType = GetType(ThreadAbortException) Then Thread.ResetAbort()
If stoppedTesting Then Exit For
Catch ex As Exception
If stoppedTesting Then Exit For
End Try
Catch ex As Exception When TypeOf ex Is ThreadAbortException OrElse TypeOf ex Is ThreadInterruptedException
e.Cancel = True
Log("Background worker thread was interrupted!")
Log("Background worker thread was interrupted!", Color.Red, New Font("Microsoft Sans Serif", 9, FontStyle.Bold))
Catch ex As Exception
Utils.PreserveStackTrace(ex)
Log("Error when doing background work!" & vbCrLf & Utils.ReadException(ex), Color.Red, New Font("Microsoft Sans Serif", 9, FontStyle.Bold))
Finally
StopCommunication()
End Try
End Sub
答案 0 :(得分:0)
BackgroundWorker.CancelAsync()
没有立即取消线程,它实际上在队列上发布了STOP消息,因为你可以检查BackgroundWorker.isCancellationPending
是否设置为true,如果你想立即取消,你可以有一个全局布尔并设置它,如果你可以取消线程。在Do_Work()方法中,您可以定期检查布尔值,如果已设置,则运行Exit Sub
。
这样的事情应该做
Else 'if thread is working normally
cancelThread = true
tEO.DoWorkEventArgs.cancel = True
并在您的Do_Work子
中For Each testStep In stepList
Try
If cancelThread Then
Exit Sub
这将彻底停止 BackgroundWorker ,并允许您运行 RunWorkerCompleted 例程。在其中,您可以检查 cancelThread ,以了解 BackgroundWorker 是成功运行还是已中止。
更新2
再次浏览代码后,为什么需要一起使用BackgroundWorker和Thread?如果您想立即取消,请仅使用Thread。此外,您只需要一个TRY..Catch用于整个函数,这样就可以确保线程退出。您始终可以将线程分配给任何内容,垃圾收集器将负责为您释放资源(如果您关注ABORTED)
Dim myThread As Thread = new Thread(new ThreadStart(yourFunctionForCommunication))
myThread.Start()
在你的功能中
Try
.. Do your work
Catch Ex As ThreadAbortException
Exit Sub;
Finally
//Do your cleanup code here
End Try
中止电话
myThread.Abort()
While mythread.ThreadState <> ThreadState.Aborted
End While
myThread = Nothing
但是我应该警告你,中止线程不是一个安全的过程。见MSDN Post。
如果您仍想使用后台工作人员,我建议您查看List<dynamic>
。添加所有Communicatewithdevice1()....to 20()
然后在循环中使用它,这样你就不必编写If条件20次。查看帖子Here