Home > Software engineering >  App is unresponsive after AcceptTcpClient()
App is unresponsive after AcceptTcpClient()

Time:10-14

When I run two instances of my application they should connect and be able to send message hello to other application. I know they connect because the client side will show that the message has sent and even received the message from the server. However only the client side is visible. The server is "frozen" as soon as I click start. Am I using something wrong? Image of frozen and visible app

private void Startbutton_Click(object sender, RoutedEventArgs e)
    {
        try
        {

            listener = new TcpListener(localAddr, port);
            ChatScreentextBox.AppendText("waiting for connection..."   "\n");
            listener.Start();

            // Buffer for reading data
            Byte[] bytes = new Byte[256];
            String data = null;

            while (true)
            {
                TcpClient client = listener.AcceptTcpClient();
                

                data = null;

                // Get a stream object for reading and writing
                NetworkStream stream = client.GetStream();

                int i;

                // Loop to receive all the data sent by the client.
                while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    // Translate data bytes to a ASCII string.
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                    ChatScreentextBox.AppendText(data);

                    // Process the data sent by the client.
                    data = data.ToUpper();

                    byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

                    // Send back a response.
                    stream.Write(msg, 0, msg.Length);
                    ChatScreentextBox.AppendText(data   "connection");
                }

                // Shutdown and end connection
                client.Close();
            }                
        }
        catch (SocketException ex)
        {
            MessageBox.Show(ex.Message.ToString());
        }
        finally
        {
            // Stop listening for new clients.
            listener.Stop();
        }

    }

private void Connectbutton_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            // Create a TcpClient.
            // Note, for this client to work you need to have a TcpServer
            // connected to the same address as specified by the server, port
            // combination.
            Int32 port = 88;
            TcpClient client = new TcpClient("127.0.0.1", port);

            // Translate the passed message into ASCII and store it as a Byte array.
            Byte[] data = System.Text.Encoding.ASCII.GetBytes("hello");

            // Get a client stream for reading and writing.
            //  Stream stream = client.GetStream();

            NetworkStream stream = client.GetStream();

            // Send the message to the connected TcpServer.
            stream.Write(data, 0, data.Length);

            //Console.WriteLine("Sent: {0}", message);
            ChatScreentextBox.AppendText(data   "\n");


            // Receive the TcpServer.response.

            // Buffer to store the response bytes.
            data = new Byte[256];

            // String to store the response ASCII representation.
            String responseData = String.Empty;

            // Read the first batch of the TcpServer response bytes.
            Int32 bytes = stream.Read(data, 0, data.Length);
            responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
            ChatScreentextBox.AppendText("you:"   responseData   "this\n");

            // Close everything.
            stream.Close();
            client.Close();
        }
        catch (ArgumentNullException ex)
        {
            MessageBox.Show(ex.Message.ToString());
        }
        catch (SocketException ex)
        {
            MessageBox.Show(ex.Message.ToString());
        }
        
    }

CodePudding user response:

You're accepting a TCPClient on a button's Click event in an infinite while loop. This is the cause of the application becoming unresponsive.

What you need to do is run this on a separate thread. BackgroundWorker is my preferred way of doing it. Task is a relatively new and popular one too.

There is a ton of examples out there on how to use both. In a nutshell, if you go with the BackgroundWorker, you need to create a field of type BackgroundWorker, have all your "smarts" in the DoWork event, then from the button Click event just call the .RunWorkerAsync() method.

If this is unclear and you need more help, just comment here.

CodePudding user response:

When you accept the connection and start (the while loop) to read data from the connection it is blocking action and you are running this action on the main thread (which is where the update UI routine is running). When you accept the connection you are reading the data but the UI never gets to update because the thread is still reading/waiting for data.

To fix this you need to run this reading action in a separate thread to handle the reading and processing. You can see an example here.

To learn more about threading in C# see an example here or read the Microsoft docs.

  • Related