0
votes

I implemented a TCP Client using a thread opening a socket to a server and reading data from it in synchronous way. When the line String thisLine = aReadStream.ReadLine(); blocks because there is no data to read from the socket and I try to perform a Thread.Abort to kill the thread ( since it is blocked on that ReadLine() ) I expect to be able to catch a ThreadAbortException BUT I can't.

The thread remains blocked on that ReadLine() and is not killed. Below the code I am using in my Thread.

Do you know why and what I am doing wrong and what to do to unblock that ReadLine()?

private void readSocket_andTriggerEvents()
{            
    TcpClient aClient = null;         

    try
    {
        aClient = new TcpClient();
        aClient.Connect(_HOST, _PORT);
        Trace.WriteLine("Socket Connected");

        NetworkStream aStream = aClient.GetStream();
        StreamReader aReadStream = new StreamReader(aStream);
        int nTimes = 0;

        while (this.isSocketThreadStarted) 
        {

            String thisLine = aReadStream.ReadLine(); // when no data
            // is available the application hangs here.
            // Thread.Abort doesn't work!
           }
    }                
    catch (ThreadAbortException ex)
    {
        Trace.WriteLine("The Thread was brute-forced killed");
        // I never come here!!
    }
    catch (SocketException ex)
    {
        Helper.ShowErrorMessage(ex);
    }
    finally{
        aClient.Close();
        Trace.WriteLine("socket closed");
     }

}
2
Shutdown the socket for input from another thread. That will cause the read to encounter end of stream, whereupon t should close the socket and exit the thread,user207421

2 Answers

2
votes

Close the socket from a different thread. This should throw a SocketException when ReadLine is blocked.

0
votes

Don't use StreamReader with network streams. It just doesn't work well with infinite streams.

As for why Thread.Abort doesn't work, that's really simple - Thread.Abort only works when the thread is either in WaitSleepJoin state or similar. If the thread is running, it has to be in managed code - a blocking socket call is most likely running(/blocking) in unmanaged code, thus the Abort cannot work until it returns. There's no way to "kill" a thread - the smallest thing that can be (more or less) safely killed is a process.

That's of course why Thread.Abort magically starts working if you close the socket afterwards - that unblocks the thread and causes it to go back to managed code, where Thread.Abort can do its hacky magic.