我正在开发一个微型UDP控制台,以发送一些数据来测试某些GPRS设备,因此我修改了一个在CodeProject中发现的示例,该示例使用一个线程。但是当我想退出该应用程序时遇到问题,即使我做类似的事情,treahd也会拒绝停止

If UdpOpen Then
   ThreadReceive.Abort()
   Me.Dispose()
   UdpOpen = False
End If

它在第一行代码上停止了
Private Sub UdpReceive()
    Dim receiveBytes As [Byte]() = receivingUdpClient.Receive(RemoteIpEndPoint) '<--Halt here
    IpRemote(RemoteIpEndPoint.Address.ToString)
    Dim BitDet As BitArray
    BitDet = New BitArray(receiveBytes)
    Dim strReturnData As String = System.Text.Encoding.ASCII.GetString(receiveBytes)
    If UdpOpen Then
        StartUdpReceiveThread(CInt(RemotePortLbl.Text))
    End If

    PrintLog(strReturnData)
End Sub

因此,我进行了一些研究,通常在此网页中找到解决方案
Stop a thread that prevents program to close?

而且,正如第一个评论所述,我将isBackground属性设置为True,它可以工作,现在的问题是为什么?

有人对它的工作原理有更深入的了解吗?

最佳答案

仅当CLR知道这样做是安全的时,线程才可以中止。当线程被深埋在操作系统调用内部时,情况并非如此。从根本上讲,这是不安全的,因为CLR无法知道线程是否已获取任何需要再次释放的内部操作系统锁。

通过将IsBackground属性设置为true,可以告诉CLR可以不中止线程,而将其留给操作系统来清理需要释放的所有内容。任何已采取的锁定都不会再导致任何问题,因为无法再运行任何可能导致死锁的代码。操作系统负责释放套接字使用的OS资源。如果您的程序由于任何其他原因而中止,就像您通过“任务管理器”终止该程序一样,它的作用就很大。

正确的方法是只调用套接字的Dispose()方法。这就拉动了操作系统调用的脚垫,它将停止等待接收任何东西,因为套接字是一只死了的鹦鹉。 Receive()调用将完成ObjectDisposedException,准备对其进行捕获。

另一个非常常见的情况是根本不使用线程,而是使用BeginReceive()。清理的工作方式大致相同,当您调用Dispose()时,回调将运行。当您调用EndReceive()时,您将获得ObjectDisposedException。以同样的方式,准备好捕获它并快速退出,而不用对套接字做任何其他事情。

否则,使用Thread.IsBackground是处理关机的一种相当合理的方法,前提是您不必做任何复杂的事情来告诉网络另一端的程序您不再监听消息。

关于vb.net - 为什么仅在isBackground属性设置为true时Thread.Abort才起作用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22762580/

10-12 15:22