在引擎盖下的阻塞任务中取消令牌
Cancel Token within Blocking Task under the hood
我有两个按钮可以启动和停止 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
是一些从 TcpClient 读取的方法。我的问题是,在我通过单击按钮停止服务器之前,我的服务器被阻止在
try {c = _listener.AcceptTcpClient();}
那么单击取消按钮如何杀死 taskListener
?没有 ManualResetEvent
或 ManualResetEventSlim
?我可以在服务器关闭和服务器重启之间切换。幕后发生了什么?我的目标是 .NET 4.0
So how does clicking the cancel button kill the taskListener?
当您在取消事件处理程序中调用 TcpListener.Stop
时,它会在内部关闭基础 Socket
,并引发 SocketException
。这个异常被你的 catch
all 块吞没了,它只是打破了循环。
文档明确说明了这一点(强调我的):
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.
您可以通过在 catch
块中打印出异常来看到这一点:
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");
}
我有两个按钮可以启动和停止 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
是一些从 TcpClient 读取的方法。我的问题是,在我通过单击按钮停止服务器之前,我的服务器被阻止在
try {c = _listener.AcceptTcpClient();}
那么单击取消按钮如何杀死 taskListener
?没有 ManualResetEvent
或 ManualResetEventSlim
?我可以在服务器关闭和服务器重启之间切换。幕后发生了什么?我的目标是 .NET 4.0
So how does clicking the cancel button kill the taskListener?
当您在取消事件处理程序中调用 TcpListener.Stop
时,它会在内部关闭基础 Socket
,并引发 SocketException
。这个异常被你的 catch
all 块吞没了,它只是打破了循环。
文档明确说明了这一点(强调我的):
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.
您可以通过在 catch
块中打印出异常来看到这一点:
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");
}