c# – Interrupting a thread with an eternal loop

Question:

I need to listen to the port all the time while the utility is running, and when commands are received on it, perform certain actions. The utility itself is implemented in the form of a WinForms form, and when it starts, a separate thread with an eternal loop is called. Everything looks like this

ServThread = new Thread(new ThreadStart(ServStart));
ServThread.IsBackground = true;
ServThread.Start();

and further already in this thread

Listener = new TcpListener(LocalPort);
Listener.Start();
while (true)
{
    TcpClient client = Listener.AcceptTcpClient();
    //что-то делаем...
} //завершили итерацию

The problem is this – if you log out (win7, xp), then it asks to forcibly terminate the program http://joxi.ru/ZrJE6y8t8lQgAj . Apparently, because of the eternal cycle. How can this problem be solved?

Answer:

Try asynchronous interface.

async Task<TcpClient> AcceptAsync(TcpListener listener, CancellationToken ct)
{
    using (ct.Register(listener.Stop))
    {
        try
        {
            return await listener.AcceptTcpClientAsync();
        }
        catch (SocketException e)
        {
            if (e.SocketErrorCode == SocketError.Interrupted)
                throw new OperationCanceledExeption();
            throw;
        }
    }
}

Now you don't need a separate thread and you can write like this:

m_cts = new CancellationTokenSource();

try
{
    var listener = new TcpListener(LocalPort);
    listener.Start();
    while (true)
    {
        TcpClient client = await AcceptAsync(listener, m_cts.Token);
        //что-то делаем...
    }
}
catch (OperationCanceledException)
{
    // операция оборвана
}

and of course

void StopListener()
{
    m_cts.Cancel();
}

Don't forget to call StopListener when the program terminates.

Scroll to Top