如何阻止非响应的线程

时间:2012-08-03 14:50:43

标签: c# multithreading

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

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

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

3 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:2)

您是否考虑过设置ReceiveTimeout

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

答案 2 :(得分:0)

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