我正在开发一个小型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?
而且,正如第一条评论中所述,我转向True isBackground属性并且它有效,现在问题是为什么?
有人深入了解它的工作原理吗?
答案 0 :(得分:7)
当CLR知道这样做是安全的时,线程才可以中止。当线程深埋在操作系统调用中时,情况不会如此。这基本上是不安全的,因为CLR无法知道线程是否已获取需要再次释放的任何内部操作系统锁。
通过将IsBackground属性设置为 true ,您告诉CLR可以中止不的线程,但将其留给操作系统进行清理任何需要释放的东西。任何采取的锁都不会导致任何问题,因为任何代码都无法再运行可能会死锁。操作系统负责释放套接字使用的OS资源。就像你的程序因任何其他原因而中止一样,就像你用任务管理器终止它一样。
执行此操作的正确方法是只调用套接字的Dispose()方法。这会拉动操作系统调用的地垫,它将停止等待接收任何东西,因为套接字是死鹦鹉。 Receive()调用将以ObjectDisposedException完成,准备捕获它。
另一个非常常见的情况是根本不使用线程而是使用BeginReceive()。清理工作方式大致相同,当您调用Dispose()时,回调将运行。当您调用EndReceive()时,您将获得ObjectDisposedException。同样的方式,准备抓住它并快速离开而不用插座做任何其他事情。
使用Thread.IsBackground是处理关闭的一种非常合理的方法,假设你不必做任何复杂的事情来告诉你在线路的另一端停止监听消息的程序。
答案 1 :(得分:2)