AcceptSocket不遵守Thread.Abort请求

Ral*_*ton 6 c# sockets multithreading

我的理解是Thread.Abort应该在被阻塞的线程上引发一个ThreadAbortException,但是在处理时似乎不是这种情况TcpListener.AcceptSocket.以下是该问题的最基本说明:

class Program
{
    static void Main(string[] args)
    {
        Thread thread = new Thread(Listen);
        thread.Start();
        Thread.Sleep(1000); // give it a second to get going
        Console.WriteLine("Aborting listener thread");
        thread.Abort();
        thread.Join();
        Console.WriteLine("Listener thread finished press <enter> to end app.");
        Console.ReadLine();
    }
    static void Listen()
    {
        try
        {
            Console.WriteLine("Starting to listen");
            TcpListener listener = new TcpListener(IPAddress.Any, 4070);
            listener.Start();
            Socket socket = listener.AcceptSocket();
            Console.WriteLine("Connected!");
            return;
        }
        catch (ThreadAbortException exception)
        {
            Console.WriteLine("Abort requested");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

thread.Abort()呼叫应停止AcceptSocket并执行ThreadAbortException处理.但这并没有发生.

AcceptSocket换掉我的ListenAsync的Listen包装器,调用它BeginAcceptSocket:

static void ListenAsync()
    {
        try
        {
            ManualResetEvent clientConnected = new ManualResetEvent(false);

            Console.WriteLine("Starting to listen");
            TcpListener listener = new TcpListener(IPAddress.Any, 4070);
            listener.Start();
            clientConnected.Reset();
            var iasyncResult = listener.BeginAcceptSocket((ar) =>
            {
                Socket socket = listener.EndAcceptSocket(ar);
                Console.WriteLine("Connected!");
                clientConnected.Set();
            }, null);
            clientConnected.WaitOne();

            return;
        }
        catch (ThreadAbortException exception)
        {
            Console.WriteLine("Abort requested");
        }
    }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它"似乎"工作正常.线程正在执行WaitOne时捕获ThreadAbortException.然而,调用BeginAcceptSocket创建的线程仍在运行并且能够接受套接字(我通过使用Telnet打开该端口来验证这一点)

最后,我添加了Listener.Stop作为TheadAbortException处理程序的一部分,并尝试捕获EndAcceptSocket调用(因为套接字由Stop​​处理)

这真的是启动和停止监听套接字连接的最佳方法吗?

JSB*_*ոգչ 7

Thread.Abort不中止正在侦听套接字的线程的原因是因为该线程被内部listen()调用内部(道德等同)阻塞.在ThreadAbortException只能通过在CLR实际执行CLR提高,并调用过程中listen线程实际上是把一个非托管的系统调用里面.一旦调用listen返回并在CLR内部恢复执行,就可以继续线程中止.

我的建议不要使用Thread.Abort().如果您决定采用该路线,则可以使用与第二个示例中的技术类似的技术.但是,最好使用不同的方法,只需Listener.Stop()在关闭线程侦听器时调用即可.

  • @Ralph:从广义的角度来看,'Thread.Abort`有问题,因为:a)(如你所见),它给出了错误的感知,即目标线程将立即(甚至*很快*)被中止,但CLR受到非托管代码的支配,并且b)它是破坏性的,并且没有告知线程在中止时将处于什么状态.强烈建议您使用某种类型的取消/中止标志,并尽可能使用带有超时的阻止方法.通过这种方式,您可以检查取消标记并执行当时适当的清理(如果有). (3认同)