1

I am working on c# winforms. I have a rich textbox in my main form. Now I am using a class HandleClient in which I am using a thread in which I am calling a function. In that function, I have made a new object of my main form. My code is below

Flow

First of all, I am passing a port number via user and on button click, I am going to listen to it. For that, I have a class named Server

Main Form

port = Convert.ToInt32(tbPort.Text);
Server server = new Server(port);
if (btnListen.Text == "Listen")
{
     btnListen.Text = "Close";
     server.start();
}

The above object is created and the start method is called

Server Class

public Server(int port)
{
   this.port = port;
}

 public void start()
 {
        listner = new TcpListener(new IPEndPoint(IPAddress.Any, port));
        listner.Start();
        listnerthread = new Thread(new ThreadStart(Listner));
        listnerthread.Start();
 }

public void Listner()
{
        while (true)
        {
            try
            {

                TcpClient C = listner.AcceptTcpClient();
                HandleClient client = new HandleClient();
                client.startClient(C);

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in listner");
                Console.WriteLine(ex.Message);
            }
        }
}

The above method is listening to the port. Also, my handle client function is also called. In which I am trying to display the incoming string to the rich text box

Handle Client

 // Buffer to store the response bytes.
byte[] data = new byte[9999];

Thread comThread;
public void startClient(TcpClient inClientSocket)
{
   this.clientsocket = inClientSocket;
   comThread = new Thread(doChat);
   comThread.Start();
}

private void doChat()
{
        MainForm form = new MainForm();

        while ((true))
        {
            try
            {
                // Read the first batch of the TcpServer response bytes.
                NetworkStream stream = clientsocket.GetStream();
                stream.ReadTimeout = 1000;
                int bytes = stream.Read(data, 0, data.Length);                 

                responseData = BitConverter.ToString(data,0,bytes); 
                form.rtBRecievedData.Text = responseData;

                stream.Close();
                clientsocket.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(" >> " + ex.ToString());
                comThread.Abort();
            }
        }
}

The value of responseData is 01-01-01-01-00-01-00-19-F4-09-10-00-00-00-00-30-30-32-39-39-38-30-30-35-35-36-31-00-01-00-01-00-01-00-15-AA-10-00-00-00-00-30-30-32-39-39-38-30-30-35-35-36-31-12-00-12

Now the main issue is that this string is not displaying on rich text box. I might be missing something that I am not able to understand.

Any help would be highly appreciated.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Moeez
  • 494
  • 9
  • 55
  • 147
  • Where do you ever show the form? – Ron Beyer Dec 31 '19 at 05:03
  • @RonBeyer I am using the form to send a port number then receiving data which is on that port – Moeez Dec 31 '19 at 05:11
  • Please check that "BitConverter.ToString(data,0,bytes)" is returning the string value. It can return a blank. – Nurhan Dec 31 '19 at 05:35
  • @Nurhan yes its returning a string – Moeez Dec 31 '19 at 05:37
  • @Faisal When or where do you call the Show() method of the form? – Nurhan Dec 31 '19 at 05:40
  • @Nurhan I have updated my question you can see it. I answered your question – Moeez Dec 31 '19 at 06:56
  • As I understood from your code, you try to reach the main form's textbox from the clients.cs but you are creating a new Main form which is another instance. You can not use that way. (There are lots of chat program example you can use in the internet, I suggest you googgle them:)) – Nurhan Dec 31 '19 at 07:37

2 Answers2

1

Your problem is that you are attempting to display the information in a TextBox on a new instance of MainForm (upon which you have never called Show()) rather than your existing MainForm, in which the user has entered the port. To fix this, your HandleClient class needs a reference to the existing form. Add fields to both your Server and HandleClient classes and adjust your constructors accordingly:

public Server(int port, Form mainForm)
{
    this.port = port;
    this.mainForm = mainForm;
}

public HandleClient (Form mainForm)
{
    this.mainForm = mainForm;
}

Now when creating the Server, you pass a reference to the current form with thethis keyword and hence on to the HandleClient.

Finally you remove the line creating a new MainForm and use the field instead.

Jonathan Willcock
  • 5,012
  • 3
  • 20
  • 31
  • I have tried your way but it's giving me an exception `Object reference not set to an instance of an object` and `this.mainForm` is `null` – Moeez Dec 31 '19 at 10:01
  • I have done the following `public MainForm mainForm { get; set; }` then `Server server = new Server(port, this.mainForm);` inside `server.cs` I have declared `public int port { get; set; } public MainForm mainForm { get; set; }` after that i have done `public Server(int port, MainForm mainForm) { this.port = port; this.mainForm = mainForm; }` – Moeez Dec 31 '19 at 10:16
  • In my `server.cs` inside the listener, I have done the following `HandleClient client = new HandleClient(this.mainForm);` – Moeez Dec 31 '19 at 10:17
  • Now in my `HandleClient.cs`, I have declared `public MainForm mainForm { get; set; }` and then `public HandleClient(MainForm mainForm) { this.mainForm = mainForm; }` – Moeez Dec 31 '19 at 10:19
  • Finally, inside my `doChat()` method I have done `mainForm.rtBRecievedData.Text = responseData;` after this line I am getting exception – Moeez Dec 31 '19 at 10:20
  • You should just have `Server server = new Server(port, this)` not `this.mainForm`. The form doesn't need a reference to itself. – Jonathan Willcock Dec 31 '19 at 10:38
  • Now I am getting exception `Cross-thread operation not valid: Control 'rtBRecievedData' accessed from a thread other than the thread it was created on` – Moeez Dec 31 '19 at 11:27
  • You need to use Invoke in order to access the UI from a thread. See Marc Gravell's answer [here](https://stackoverflow.com/questions/661561/how-do-i-update-the-gui-from-another-thread/1803319) Just use `RichTextBox.Invoke` for `Label.Invoke` – Jonathan Willcock Dec 31 '19 at 11:58
  • The given method in the link provided by your does works. But the resulting output is displaying in a rich text box while I am in debug mode. But when I tried to run it it's not displaying :( – Moeez Jan 01 '20 at 05:13
  • Happy New Year. have a mega hangover and am only on my phone (not at my PC), so please treat this with caution. Are you sure that it is not working in run mode? Is it possible that the value is being set, but immediately overwritten with an empty string? Try testing for null/empty string before calling `Invoke`. – Jonathan Willcock Jan 01 '20 at 09:01
  • Happy New Year to you also :) All the things are working perfectly now. Thanks for the help :) – Moeez Jan 01 '20 at 09:02
0
form.rtBRecievedData.Text = responseData; 

is within a loop. But there is no Thread.Sleep() method.

form.rtBRecievedData.Text can be replace by empty string of responseData in the next round of execution of loop.

use the following code,

form.rtBRecievedData.Text += responseData; 

resolve the issue. And better to have sleep within the loop to give a delay in reading the port.

Banukobhan Nagendram
  • 2,335
  • 3
  • 22
  • 27