【问题标题】:How to stop a non responsive thread如何停止无响应的线程
【发布时间】:2012-08-01 15:23:36
【问题描述】:

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

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

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

【问题讨论】:

  • 谢谢,但这不是我的问题。
  • 我认为线程中止根本不安全。
  • 在底层Socket 上调用Shutdown。这将导致线程出错。
  • @DavidSchwartz 说了什么,以及为什么只有一个 FTP 客户端?为什么每个线程不能有自己的?

标签: c# multithreading


【解决方案1】:

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

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

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

【讨论】:

  • “真正的异步”,如 .NET 4.5 (Visual Studio 2012) 和 ReceiveAsync?也没有什么可以取消的......
  • @Peter:没有什么可以取消的。 ReceiveAsync 立即返回,并在收到数据时运行您指定的回调。该线程没有阻塞任何东西。你可以很容易地在你的回调中说“如果我被处置了,不要做任何事情”。
  • 我认为我误读了您的帖子,因为建议使用 ReceiveAsync 更容易取消,而不是使用异步方法可能会减轻取消的需要...
【解决方案2】:

您是否考虑过设置ReceiveTimeout

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

【讨论】:

  • 我无权访问 Socket.ReceiveTimeout 属性,因为它位于 FTPClient dll 的远端。我的问题是没有识别非响应线程,尽管看门狗是一种很好的技术。这就是我确定非响应线程后要做的事情。
  • 如果线程卡在Socket.Receive(),没有好的方法可以终止线程。它很可能会使您的程序处于不稳定状态。它是商业的还是第 3 方的 FTPClient dll?
  • 我正在使用 CodePlex 的 System.Net.FtpClient,因为它是推荐的。
  • 根据这个页面netftp.codeplex.com/discussions/273132应该有ReadTimeoutWriteTimeout,以及异步BeginConnect()/EndConnect()方法。希望它会有所帮助。
【解决方案3】:

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

【讨论】:

  • 那么就可以了。数据传输回调用应用程序可能很糟糕
  • 很抱歉,我没有遵循“数据传输回调用应用程序可能很讨厌”。你的意思是一些内存映射文件不适合这个目的吗?
  • 内存映射文件可以做到这一点
猜你喜欢
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 1970-01-01
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
相关资源
最近更新 更多