Reputation: 1618
I have two buttons that start and stop a TcpListener
.
private void buttonStartServer_Click(object sender, EventArgs e)
{
ThreadPool.SetMinThreads(50, 50);
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
_listener = new TcpListener(ipAddress, 5000);
cancelSource = new CancellationTokenSource();
CancellationToken token = cancelSource.Token;
var taskListener = Task.Factory.StartNew(
(t) => Listener(token),token,TaskCreationOptions.LongRunning);
}
void Listener(CancellationToken token)
{
_listener.Start();
while (!token.IsCancellationRequested)
{
TcpClient c;
try
{
c = _listener.AcceptTcpClient();
}
catch
{
break;
}
Task t = Task.Factory.StartNew(() => Accept(c))
.ContinueWith(ant => richTextBoxMessage.AppendText(ant.Result), _uiScheduler);
}
}
private void buttonStopServer_Click(object sender, EventArgs e)
{
cancelSource.Cancel();
_listener.Stop();
richTextBoxMessage.AppendText("Server shutdown");
}
Accept
is some method that reads from the TcpClient. My question is, before I stop the server by clicking the button, my server is blocked at
try {c = _listener.AcceptTcpClient();}
So how does clicking the cancel button kill the taskListener
? Without having a ManualResetEvent
or ManualResetEventSlim
? I am able to toggle between server shutdown and server restart. What's going on under the hood? I'm targeting .NET 4.0
Upvotes: 4
Views: 119
Reputation: 149538
So how does clicking the cancel button kill the taskListener?
When you call TcpListener.Stop
in your cancel event handler, internally it will close the underlying Socket
, and raise a SocketException
. This exception is swallowed by your catch
all block, which simply breaks the loop.
The documentation state this explicitly (emphasis mine):
Stop closes the listener. Any unaccepted connection requests in the queue will be lost. Remote hosts waiting for a connection to be accepted will throw a SocketException. You are responsible for closing your accepted connections separately.
You can see this by printing out the exception in the catch
block:
TcpClient c;
try
{
c = _listener.AcceptTcpClient();
}
catch (SocketException e)
{
Debug.WriteLine("Socket exception was raised: {0}", e);
if (e.SocketErrorCode == SocketError.Interrupted)
Debug.WriteLine("Blocking listen was interrupted");
}
Upvotes: 3