用'aborted'状态销毁Thread

时间:2017-07-13 05:19:27

标签: vb.net multithreading

在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
  1. 我可以做些什么来完全破坏线程?
  2. 如果没有可能,可以立即退出我的“DoWork”方法吗?

1 个答案:

答案 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