Why Thread.Abort only works if is isBackground property set to true?
Asked Answered
R

2

5

I'm developing a tiny UDP console to send some data to test some GPRS devices so I modify an example that I found in CodeProject that it uses one thread; but I get an issue when I want to exit the application, the treahd refuses to stop even if I do something like

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

It halt on the first code line

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

So I do some research and found, usually, in this Web page the solution Stop a thread that prevents program to close?

And, as says on the first comment, I turn to True the isBackground property and it work, now the question is Why?

Does somebody knows more in deep how it works?

Revers answered 31/3, 2014 at 13:17 Comment(0)
B
7

A thread is only abortable when the CLR knows that it is safe to do so. Which will not be the case when the thread is buried deep inside an operating system call. That is fundamentally unsafe since the CLR cannot know if the thread has acquired any internal operating system locks that need to be released again.

By setting the IsBackground property to true, you tell the CLR that it is okay for the thread to not be aborted but leave it up to the operating system to clean-up anything that needs to released. Any taken locks cannot cause any problems anymore since there is no way for any code to run anymore that could deadlock. The operating system takes care of releasing the OS resources used by the socket. Much as it does if your program aborts for any other reason, like you terminating it with Task Manager.

The proper way to do this is to just call the socket's Dispose() method. That pulls the floor mat on the operating system call, it will stop waiting for anything to be received because the socket is a dead parrot. The Receive() call will complete with an ObjectDisposedException, be prepared to catch it.

Another very common scenario is to not use a thread at all but to use BeginReceive(). Cleanup works much the same way, when you call Dispose() then the callback will run. When you call EndReceive() then you get the ObjectDisposedException. Same way, be prepared to catch it and get out quick without doing anything else with the socket.

Using Thread.IsBackground is otherwise a pretty reasonable way to deal with shutdown, assuming you don't have to do anything intricate to tell the program on the other end of the wire that you stop listening for messages.

Biggerstaff answered 31/3, 2014 at 13:42 Comment(5)
Thanks for answer,my UDP console sends an ACK packet to the remote device for every packet received, so if the remote device don't receive the ACK he understand that the packet don't reach my console or the console is not running, so I don need to send anything to the remote device to warning it about. The way that I'm currently managing the thread, does not any chance to get a lonely thread walking around the OS, right?Revers
Too vague, I don't know what "walking" threads look like. Or whether ACK means "I received it" or "I processed it". Implementing your own version of TCP is usually a mistake. Reliable UDP has been done many times before.Biggerstaff
With "walking threads" I mean a thread that still running even if I close my application. Yes, ACk stands for ACKnowledge. I didn't create my own TCP stack I have a protocol to emulate since it is already implemented in the servers of my job.Revers
Asked and answered. Talk to somebody that knows the protocol, fairly unlikely you can just terminate your program without that server being unaware of it.Biggerstaff
The console does not connect with the server, it's emulate it in order to test the remote device that usually connects to the main server. My UDP console is only for technicians's laptop to test the remote device, doesn't run in any server.Revers
S
2

.NET has built-in support for receiving UDP asynchronously. See this:

So you don't need to use threads in this case.

Savoy answered 31/3, 2014 at 13:20 Comment(1)
Thanks for answer, I'm currently using thread so I think I'm going to keep in this way for now, but that is another interesting way to do the same. Thanks for sharing.Revers

© 2022 - 2024 — McMap. All rights reserved.