0

I am having a TCP client connect to the server. Once it is connected, it should change the label to "Connected". The problem I'm having is that when I create a thread, it's static no matter what.

public static Thread waitForConnectionThread = new Thread(waitForConnection);

This means the method it'll be running also has to be static, which in turn causes me not to be able to access the UI controls.

public static void waitForConnection()
    {
        server.Start();
        client = server.AcceptTcpClient();
        labelControl1.Text = "Connected";  <-----------------
    }

I also tried Control.Invoke, but since I'm on static thread I wasn't able to get it to work. Is there possibly a way around this?

Meme Machine
  • 949
  • 3
  • 14
  • 28
  • What do you mean "no matter what"? What happens if you remove `static` keyword? Why does it need to be static? – Alex Jan 15 '17 at 05:01
  • If I remove the 'static' keyword from the Thread and the method, I get "A field initializer cannot reference the non-static field, method, or property 'Form1.waitForConnection()' – Meme Machine Jan 15 '17 at 05:03
  • 1
    If your static thread is used for network IO, then it may be a good idea to **not** update UI from this thread. Instead, create a `public static ManualResetEvent clientConnected;` event in the main Form and a local event-handler, and then update the UI as required. Also, take a look at: [How to update the GUI from another thread in C#?](http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c) [How to invoke a UI method from another thread](http://stackoverflow.com/questions/10170448/how-to-invoke-a-ui-method-from-another-thread) – Serge Jan 15 '17 at 05:11
  • @lol then get an instance of the Form1 :) – Alex Jan 15 '17 at 05:16
  • @Alex I read that it was bad practice to do that, but I suppose I don't really have many other options – Meme Machine Jan 15 '17 at 05:21
  • @Serge Sounds very complicated, but I'll give it a try. Thanks – Meme Machine Jan 15 '17 at 05:21
  • Sorry, instead of `ManualResetEvent`, use simple events. Take a look @ https://www.dotnetperls.com/event – Serge Jan 15 '17 at 05:29
  • @lol yes it isn't a good practice, as pointed out by Serge. His approach is preferable. – Alex Jan 15 '17 at 05:44
  • 1
    Possible duplicate of [How to update the GUI from another thread in C#?](http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c) – Ken White Jan 15 '17 at 05:45
  • What do your mean with "static thread"? A thread is a string of execution and as such can not be static or instance. Where your `Thread` variable is stores is irrelevant for callability. – Sefe Jan 15 '17 at 07:08

1 Answers1

0

Create a class like the following :

public class TcpConnect
{
    public Thread waitForConnectionThread;

    public event EventHandler ClientConnected;

    public TcpConnect()
    {
        waitForConnectionThread = new Thread(waitForConnection);
    }

    private void waitForConnection()
    {
        server.Start();
        client = server.AcceptTcpClient();
        RaiseClientConnected(new EventArgs());
    }

    protected void RaiseClientConnected(EventArgs args)
    {
        if (ClientConnected != null)
        {
            ClientConnected(this, args);
        }
    }
}

then inside the form create an instance from it and attach an event handler to the event ClientConnected in the created class, like the following :

        TcpConnect tcpConnect = new TcpConnect();
        tcpConnect.ClientConnected += tcpConnect_ClientConnected;

and the event handler should call the update label method, something like this :

void tcpConnect_ClientConnected(object sender, EventArgs e)
    {
        if (this.InvokeRequired)
        {
            //then it is called from other thread, so use invoke method to make UI thread update its field
            this.Invoke(new Action(() => UpdateLabelText()));
        }
        else
        {
            //then it is called from UI and can be updated directly
            UpdateLabelText();
        }

    }

    private void UpdateLabelText()
    {

        labelControl1.Text = "Connected";
    }

Hope this was useful.

Ali Ezzat Odeh
  • 2,093
  • 1
  • 17
  • 17