Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 676
E_Blue Avatar asked Mar 31 '14 13:03

E_Blue


2 Answers

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.

like image 106
Hans Passant Avatar answered Nov 16 '22 19:11

Hans Passant


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

  • UdpClient.BeginReceive

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

like image 45
Neolisk Avatar answered Nov 16 '22 20:11

Neolisk