AcceptSocket 不尊重 Thread.Abort 请求

发布于 2024-11-03 08:42:34 字数 2335 浏览 0 评论 0原文

我的理解是 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");
        }
    }
}

thread.Abort() 调用应停止 AcceptSocket 并执行 ThreadAbortException 处理程序。然而这并没有发生。

将我的 AcceptSocket 监听包装器替换为 ListenAsync,它调用 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");
        }
    }

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

最后,我添加了 Listener.Stop 作为 < code>TheadAbortException 处理程序,以及 EndAcceptSocket 调用周围的 try catch(因为套接字是由 Stop 释放的)

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

My understanding is that Thread.Abort should raise a ThreadAbortException on a blocked thread, however this does not seem to be the case when dealing with TcpListener.AcceptSocket. Here's the most basic illustration of the issue:

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");
        }
    }
}

The thread.Abort() call should stop the AcceptSocket and execute the ThreadAbortException handler. Howerver this does not happen.

Swapping out my Listen wrapper of AcceptSocket for ListenAsync which calls BeginAcceptSocket instead:

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");
        }
    }

In this case it "appears" to work fine. The ThreadAbortException is caught while the thread is doing a WaitOne. HOWEVER the thread that was created by the call to BeginAcceptSocket is still running and able to accept a socket (I verified this by opening that port with Telnet)

Finally, I added Listener.Stop as part of the TheadAbortException handler, and a try catch around the EndAcceptSocket call (since the socket is disposed by the Stop)

Is this really the best approach starting and stopping the process of listening for socket connections?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红颜悴 2024-11-10 08:42:34

Thread.Abort 不会中止正在侦听套接字的线程的原因是该线程被阻塞在 listen() 内核调用内(道德上相当于) 。 ThreadAbortException 只能在 CLR 实际执行时由 CLR 引发,并且在调用 listen 期间,线程实际上陷入非托管系统调用中。一旦对 listen 的调用返回并且 CLR 内部恢复执行,线程中止就可以继续。

我赞同不要使用 Thread.Abort() 的建议。如果您确实决定走这条路,则可以使用与第二个示例中类似的技术。但是,当您想要关闭线程侦听器时,最好使用不同的方法并简单地调用Listener.Stop()

The reason that Thread.Abort doesn't abort a thread that's listening on a socket is because that thread is blocked inside (the moral equivalent of) a listen() kernel call. The ThreadAbortException can only be raised by the CLR when the CLR is actually executing, and during a call to listen thread is actually stuck inside an unmanaged system call. Once the call to listen returns and the execution resumes inside the CLR, the thread abortion can be continued.

I second the advice not to use Thread.Abort(). If you do decide to go that route, you can use a technique similar to the one in your second example. However, you'd be better off using a different method and simply calling Listener.Stop() when you want to shut down the thread listener.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文