取消引擎盖下阻塞任务内的令牌

本文关键字:任务 令牌 引擎 取消 | 更新日期: 2023-09-27 18:26:22

我有两个按钮可以启动和停止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的呢?没有ManualResetEventManualResetEventSlim?我可以在服务器关闭和服务器重新启动之间切换。引擎盖下面发生了什么事?我的目标是.NET 4.0

取消引擎盖下阻塞任务内的令牌

那么,单击取消按钮是如何杀死taskListener的呢?

当您在取消事件处理程序中调用TcpListener.Stop时,它将在内部关闭基础Socket,并引发一个SocketException。这个异常被您的catchall块所吞噬,这只会破坏循环。

文件明确说明了这一点(重点是我的):

Stop关闭侦听器。中任何未接受的连接请求队列将丢失等待连接的远程主机accepted将引发SocketException您负责结账您单独接受的连接。

您可以通过打印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");
}