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.