5

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

根据调用堆栈,我的 FTP 客户端每隔一段时间就会在 System.Net.Sockets.Socket.Receive() 的某个地方冻结。我没有得到例外,所以无法处理这个问题。我想取消线程,因为它阻塞了其他想要使用 FTP 客户端的线程。

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

4

3 回答 3

4

不。没有线程的合作,没有安全、可靠的方法可以杀死线程。现有的机制可能非常严厉,和/或不一定有效。

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

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

于 2012-08-03T14:58:36.047 回答
2

您是否查看过设置ReceiveTimeout

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

于 2012-08-03T14:59:01.913 回答
0

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

于 2012-08-03T14:54:32.980 回答