【问题标题】:Destroy Thread with 'aborted' state销毁具有“中止”状态的线程
【发布时间】:2017-07-13 05:19:27
【问题描述】:

在 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”方法?

【问题讨论】:

  • 哎哟! Bgw 使用 Pool 线程,你甚至不应该改变它的任何属性,当然也不应该 Abort() 它!
  • 您不能也不应该处置或销毁线程。他们照顾自己。
  • @HenkHolterman 好的...您对紧急停止线程有什么想法吗?
  • 是的,避免需要。请参阅this 等等。应该避免为您自己的线程使用 Thread.Abort(),在池线程上调用它是......邪恶的。

标签: vb.net multithreading


【解决方案1】:

BackgroundWorker.CancelAsync() 不会立即取消线程,它实际上会在队列中发布 STOP 消息,因为您可以检查 BackgroundWorker.isCancellationPending 是否设置为 true,如果您想立即取消,可以使用全局 boolean 如果可以取消线程,请设置它。在您的 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&lt;dynamic&gt;。在那里添加所有Communicatewithdevice1()....to 20(),然后在循环中使用它,这样您就不必编写 If 条件 20 次。见帖子Here

【讨论】:

  • 是的..我想到了这种方法..但我实际上用检查污染了后台工作线程......想象一下,在每次与设备通信后,我可能有 20-30 次检查。 ..我需要的是一个紧急出口...
  • 怎么叫污染? @eltigre
  • 你不是在循环通信吗?如果是这样,它将被自动检查
  • 是的...但是当我循环一次时,我有:Coomunicate1(), Communicate2()....Communicate20()。为此,如果设置了布尔值,我必须检查 20 次......这不是一个很好的代码
  • 然后@eltigre 更新您的问题,以便我可以提供更好的解决方案,添加通信部分。
猜你喜欢
  • 1970-01-01
  • 2012-11-11
  • 2012-08-02
  • 1970-01-01
  • 2016-02-17
  • 2019-05-02
  • 2023-03-29
  • 1970-01-01
  • 2010-10-15
相关资源
最近更新 更多