如何阻止非响应的线程

我有一个文件传输应用程序在FTP服务器之间移动文件。 任何时候我们都可以在移动中拥有数十个文件。 为了防止泛滥FTP服务器,我有一个监视器和信号量锁系统。

我的FTP客户端经常根据调用堆栈冻结在System.Net.Sockets.Socket.Receive()内的某个地方。 我没有得到例外,所以无法解决问题。 我想取消该线程,因为它阻止了其他想要使用FTP客户端的线程。

我已经考虑启动最终在新线程中调用System.Net.Sockets.Socket.Receive()并在一段时间后中止线程的方法,但我担心在线程中止后套接字将保持打开状态。 在没有响应的线程之后,有更优雅的方法来杀死和清理吗?

没有。没有合作就没有安全,可靠的杀死线程的方法。 存在的机制可能非常严厉,并且/或者不一定有效。

  • 您可以尝试Interrupt()另一个线程,但这通常只会中断正在等待/hibernate或正在执行可能阻塞的线程。 如果它处于不涉及阻塞的事物的中间,它甚至不会看到 ,更不用说响应中断,直到它再次尝试阻塞。 如果你有一个流氓线程,那么很可能是“永远不会”。
  • Abort() 可能会杀死一个线程,但也不能保证 – 线程可能会顽固地拒绝死亡。 即使它确实死亡,也可能使您的应用领域处于可疑状态。 (假设线程在进入finally块时被中止。然后会抛出exception,并且最终块将不会运行 – 所以它释放的任何内容(锁,本机资源,等等)都将保留未发行)。
  • 显然甚至卸载app域只是中止其中的线程,因此Thread.Abort的不确定性适用 – 加上,如果它有效,它也会杀死app域中的每个线程。
  • 关于唯一相对安全且保证工作的是杀死整个过程。 如果你这样做,就无法保证外部资料的状态。 您可以保证所持有的任何资源都将被释放/关闭/不管,而不是它们处于任何特定状态(例如,“未损坏”)。

在这种情况下,更好的解决方案可能是异步接收(使用真正的异步内容( ReceiveAsync ),而不是BeginReceive / EndReceive )。 这样线程就不会被原生内容阻塞,并且更容易被中断(如果由于某种原因你仍然必须这样做;异步的好处包括你甚至不需要一个单独的线程来观看输入)。

你看过设置ReceiveTimeout了吗?

否则,您可以在每个线程中设置Watchdog属性,并检查Watchdog变量的状态以识别无响应的线程。

我建议在一个单独的进程中运行你的线程(如果可能的话)并毫不留情地杀死它。 然后OS将释放所有资源