views:

435

answers:

4

Hi,

I did search for answers already, but can't find anything similar...

I'm fairly new to C#. I need to create a program in C# using WinForms. It basically has 2 components: UI and then I need to have a process that permanently listens on a socket TCP port. If there's anything received, then I need to raise an event or something similar so I can update the UI.

Question: what is the best way to implement a process that needs to be listening all the time while the program is running?

And then, when I receive a message, how can I notify the UI that it needs to be updated?

Thanks!

+1  A: 

You could use TcpListener class. There's an example in the documentation.

Darin Dimitrov
I believe they are looking more for an architectural answer... it seems they are not sure how to integrate a TcpListener with an event driven program.
Polaris878
+1  A: 

On startup you can spawn (create) a new Thread which listens for new messages in an infinite loop. Once a message is received the thread can update some shared resource (set a flag). Of course you could make this more sophisticated if you used a synchronized queue to transfer messages. Or via WCF (even though this seems overkill for your purposes).

Manu
+1  A: 

This may not be the best way to do this, but it should work...

You could launch your TCP listener code in a new thread when the program starts... This way you have the TCP code listening while the UI is off doing other stuff. When something happens in the TCP thread, it'll have to signal the UI thread by some sort of event or event queue.

Now, in terms of updating a WinForms object when something is received, I believe only the thread that created the WinForms control can update the controls. So, you'll have to take that into account also.

This is a problem I've wrestled with before as well... In my current project I do what I mentioned above... however there is quite a bit of thread synchronization to get it working.

Polaris878
It's pretty easy to update the UI from another thread : you just need to use the Control.Invoke method by passing it a delegate that updates the UI
Thomas Levesque
+2  A: 

You can use a TcpListener that waits for incoming connections on another thread. Every time you receive a new connection, create a new thread to process it. Use Control.Invoke to update the UI from the non-UI thread. Here's a short example :

public MainForm()
{
    InitializeComponents();
    StartListener();
}

private TcpListener _listener;
private Thread _listenerThread;

private void StartListener()
{
    _listenerThread = new Thread(RunListener);
    _listenerThread.Start();
}

private void RunListener()
{
    _listener = new TcpListener(IPAddress.Any, 8080);
    _listener.Start();
    while(true)
    {
        TcpClient client = _tcpListener.AcceptClient();
        this.Invoke(
            new Action(
                () =>
                {
                    textBoxLog.Text += string.Format("\nNew connection from {0}", client.Client.RemoteEndPoint);
                }
            ));;
        ThreadPool.QueueUserWorkItem(ProcessClient, client);
    }
}

private void ProcessClient(object state)
{
    TcpClient client = state as TcpClient;
    // Do something with client
    // ...
}
Thomas Levesque
Why was I downvoted ? Please comment ! I'm open to criticism, but if I don't know what's wrong with my answer, it's not very constructive...
Thomas Levesque
It's just cosmetics, but I think you have one semicolon too much after this.Invoke(...);;(Just to clarify, that's not the reason you were downvoted, at least not by me)
Manu