Search code examples
c#winformssocketstcpclient

Design don't appear on Debug


I'm creating a C# Socket Server, it already works, but now, when I press "Start" the "design" of the application doesn't load, it's not visible.

The socket server is running correcty (I see it working in the output window), I don't see any kind of error. I start deleting parts of the code, and the design stops being visible after this line:

TcpClient client = server.AcceptTcpClient();
...

If I remove from this line to the end, it appear again.

What's going on? (sorry for my bad english)

public Form1()
{
    InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
    start();
}

private void start() {

    TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);

    server.Start();

    TcpClient client = server.AcceptTcpClient();

    Console.WriteLine("Client connected.");

}

I Think the problem is that the load is interrupted while the socket is working waiting for connections.

I'm trying to execute "start()" function on Form1_Shown but it does not work.

How can I be sure to start the socket server after the Form is full loaded?


Solution

  • server.AcceptTcpClient() is a blocking call and you are making it on the UI thread. You have a few options, here they are in the order I would do them.

    Make the function you are calling it from async and use AcceptTcpClientAsync.

    //Event handlers like `Load` are the only place you are allowed to do "async void"
    private async void Form1_Load(object sender, EventArgs e)
    {
        await start();
    }
    
    private async Task start() {
    
        TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
    
        server.Start();
    
        TcpClient client = await server.AcceptTcpClientAsync();
    
        Console.WriteLine("Client connected.");
    
    }
    

    If you can't use async/await because of the version of .NET you are targeting use BeginAcceptTcpClient to have a callback accept the client instead.

    private void Form1_Load(object sender, EventArgs e)
    {
        start();
    }
    
    private void start() {
    
        TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
    
        server.Start();
    
        server.BeginAcceptTcpClient(AcceptClient, server);
    
    }
    
    private void AcceptClient(IAsyncResult result)
    {
        var server = (TcpListener)result.AsyncState;
        TcpClient client = server.EndAcceptTcpClient(result);
    
        Console.WriteLine("Client connected.");
    }
    

    Or one other option is put the code you currently have on a background thread via a Task.Run( or similar. However, I really would not recommend this approach, you tie up a thread just waiting for a new connection, the framework already provides better ways to do this without a thread by using async/await or the begin/end pair.

    private void Form1_Load(object sender, EventArgs e)
    {
        Task.Run(() => start());
    }
    
    private void start() {
    
        TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
    
        server.Start();
    
        TcpClient client = server.AcceptTcpClient();
    
        Console.WriteLine("Client connected.");
    
    }