-1

I am developing a GUI where a user can connect to server and read the data. The data needs to be displayed on the GUI. For this I am using TabControl whose ContentTemplate is set to RichTextBox.

When the user click connect button, the UI connects to the TCP server. Here I spawn a new thread which reads data from the server. However after sometime when huge data is pumped to the RTB, the UI becomes unresponsive. I cannot move the app within the screen.

Is there any way where I can remove the older data dynamically (new data gets appeneded below) so that the RTB is not loaded much and UI should work properly. Also the app is utilizing upto 80 CPU under Processes in Task Manager

private void BtnConnect_Click(object sender, RoutedEventArgs e)
        {
            //connect
            TCPClientClass tcpClient = TCPConnHandler.ConnectToService(tbIPAddress.Text);
            if (tcpClient != null)
            {
                MessageBox.Show("Connected to " + tbIPAddress.Text);
                //open new tab
                var item = MainWindowVMObj.AddTabItem();

                Thread thTabControl = new Thread(() =>
                {
                    while (tcpClient.Connected)
                    {
                        String str = tcpClient.GetDataFromServer();
                        if (!String.IsNullOrEmpty(str))
                            tabControl1.Dispatcher.BeginInvoke((Action)(() => item.Content += str));
                        Thread.Sleep(200);
                    }
                    //item.Dispatcher.BeginInvoke
                });

                thTabControl.Start();
            }
        }

apb_developer
  • 321
  • 2
  • 9
  • 1
    You're ignoring `response`, an integer containing the number of bytes received. Read the docs. – CodeCaster Oct 16 '19 at 10:30
  • TCP is split into datagrams of max size of ~1500 bytes. Routers and server can split and recombine the datagrams. And you do not get a EOF until the TCP connection closes. You should use a Networkstream which handlesthe packing of datagrams into messages so you know when you get an end of message (your end of data). Strings in c# are classes where each character can be one or two bytes. So strings will look garbled if the alignment of the two bytes character get mis-aligned. – jdweng Oct 16 '19 at 10:33
  • 2
    @jdweng `NetworkStream` *absolutely does not* know anything about messages and the end of messages; `NetworkStream` is **purely** a `Stream` abstraction over `Socket`; it adds no framing; as for `string`s: that depends on the encoding; in OP's case they're using ASCII, so: single byte – Marc Gravell Oct 16 '19 at 10:35
  • Why is my UI becoming unresponsive. Can I delete the older data in the RTB while new one gets added dynamically. I am new to C# and WPF. Any lead would be appreciated. Thanks in advance – apb_developer Nov 13 '19 at 10:55

1 Answers1

2

Read and ReadAsync return an integer telling you how much they received; if the value is non-positive, it means the end of the data was reached (receive socket closed, etc); for a positive number, you should only look at the first (that-many) bytes in the receive buffer.

Note that this does not necessarily contain an entire message; TCP is a streaming protocol, not a message protocol; you are not guaranteed to get everything in one go, which is why when sending multiple messages on TCP you need some kind of "framing" layer, so you know where each individual message ends. Note also that when sending text using multi-byte encodings, you can receive partial characters, i.e. a 3 byte character can be received in 3 different calls to Read - hence you usually need to buffer your frames until you know you have a complete frame.

For string data, a common framing technique is "end of line", i.e. look for \r, \n, \r\n or \n\r (although other options are available). For binary data, length-prefix is the norm.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900