0

I have a WinForms application for a TCP-IP client. Once the client gets connected to a localhost server, I start a thread t1, which enters in an infinite loop to keep receiving messages from the server.

When the server is not sending any message then the thread waits INFINITELY at the statement m_DeviceServerStream.Read(instream, 0, buffersize); as shown in the code below.

Thread t1;
TcpClient m_DeviceClientSocket = new TcpClient();
    NetworkStream m_DeviceServerStream = default(NetworkStream);

public void StartClient()
{
    m_DeviceClientSocket.Connect(m_DeviceURL, m_DevicePort);
    m_DeviceServerStream = m_DeviceClientSocket.GetStream();

    t1 = = new Thread(KeepReceiveingMessages);
    t1.Start();
}

public void StopClient() //On Stop Button-click
{
    t1.Abort();
}

public void KeepReceiveingMessages()
{
    while(true)
    {
        _dataServiceConnected.Waitone()
        try
        {
            var buffersize = m_DeviceClientSocket.ReceiveBufferSize;
            byte[] instream = new byte[buffersize];

            m_DeviceServerStream.Read(instream, 0, buffersize) //THREAD T1 KEEP WAITING HERE TILL A MESSAGE IS RECEIVED FROM THE SERVER
        }
        catch(Exception e)
        {                       
           _dataServiceConnected.Reset(); //do not try to eneter again till we have a working connection
        }
    }
}

Question: If I want to close the Client application then, I want to finish the thread gracefully. But I found even if I call t1.Abort(), the thread t1 keeps running (as shown in the Visual Studio Thread-Debug window). Aborting a thread is not a good practice, so how should I do end the thread?

skm
  • 5,015
  • 8
  • 43
  • 104
  • Close the stream. See https://stackoverflow.com/a/12893018/11683 for the async version. – GSerg Sep 25 '19 at 15:58
  • @GSerg: I closed the stream and called `t1.Join(1000);` but the thread is still running. – skm Sep 25 '19 at 16:07
  • I was just looking at similar code for another posting. I found following : if(ns.DataAvailable) ns.Read(new byte[100], 0, 100); See https://stackoverflow.com/questions/1993635/alternative-to-networkstream-read-that-indicates-remote-host-has-closed-the-conn – jdweng Sep 25 '19 at 16:12
  • @skm When you close the stream, the `Read` call returns. Because you have an infinite loop, it's called again, which raises an exception because the stream is closed. If you don't observe that exception, it means this is not the actual code you're running. – GSerg Sep 25 '19 at 16:26
  • @GSerg: I do have catch-blocks and as soon as I close the stream, the thread enters into the catch-block. But still, I am not able to Abort the thread (maybe because I have a `Waitone() statement at the beginning of the while loop`). I have updated my code in the post. – skm Sep 26 '19 at 07:32
  • So your thread keeps throwing exceptions, swallowing them and continuing the infinite loop. Obviously it never terminates. You need to exit the `while` loop when a proper exception occurs. – GSerg Sep 26 '19 at 08:30
  • @GSerg: Thanks! Now, I am setting a bool variable to TRUE, break the infinite while-loop (i.e. `while (true && !_appClosing_ThreadsShouldTerminate)` ) – skm Sep 26 '19 at 09:01

1 Answers1

1

You should use WaitOne(Int32) to wait with a timeout. If WaitOne(int32) returns false, then it means that the timeout has expired and the event is not signaled. Then, you can check if you need to quit your thread graciously.

private bool volatile shouldCancel; //Dirty, but will work on Intel hardware :-)

public void KeepReceiveingMessages()
{
    while(true)
    {
        bool signaled = _dataServiceConnected.Waitone(100);
        if (!signaled && shouldCancel) return;
        try
        {
            var buffersize = m_DeviceClientSocket.ReceiveBufferSize;
            byte[] instream = new byte[buffersize];

            m_DeviceServerStream.Read(instream, 0, buffersize) //THREAD T1 KEEP WAITING HERE TILL A MESSAGE IS RECEIVED FROM THE SERVER
        }
        catch(Exception e)
        {                       
           _dataServiceConnected.Reset(); //do not try to eneter again till we have a working connection
        }
    }
}
Nick
  • 4,787
  • 2
  • 18
  • 24