【问题标题】:How do you handle a thread that has a hung call?您如何处理挂起呼叫的线程?
【发布时间】:2009-06-10 22:25:47
【问题描述】:

我有一个线程出去并尝试建立连接。在线程中,我调用了第三方库。有时,此调用会挂起,并且永远不会返回。在 UI 线程上,我希望能够通过中止线程来取消连接尝试,这应该中止对第三方库的挂起调用。

我已经调用了 Thread.Abort,但现在读到 Thread.Abort 仅在控制权返回到托管代码时才有效。我观察到这是真的,因为线程永远不会中止,而且我已经坐在 Thread.Join 上十分钟了。我应该如何处理这个挂起的线程?我应该只是取消引用并继续前进吗?我希望尽可能干净--

【问题讨论】:

    标签: c# .net asp.net multithreading


    【解决方案1】:

    随机想法:我想知道您是否可以编写第二个程序集作为执行此通信的小型控制台 exe...使用Process.Start 启动它并通过文件系统或截取标准输出来捕获结果。然后,如果它挂起,您可以终止该进程。

    可能有点苛刻 - 显然它有产生进程的开销 - 但至少应该有可能杀死它。

    【讨论】:

    • “从轨道上起飞并核爆该站点——这是唯一确定的方法。”的确,你是对的;这是终止行为不端代码的唯一有保证的安全方法。 Thread.Abort 不能保证实际中止行为不端的线程;一个真正表现不佳的线程可以劫持中止。即使取消一个 appdomain 也不一定能达到你想要的效果。如果您绝对必须终止行为不良的代码,那么您需要将其隔离到一个可终止的进程中。
    • 谢谢 Ripley... 我的意思是... Eric ;-p (我会给出 Hudson 的回复,但我必须自己使用版主工具...)
    【解决方案2】:

    你的第三方库中的这个函数没有超时取消函数?如果是这样,那是相当糟糕的设计。我认为这里不会有任何漂亮的解决方案......

    不幸的是,您无法绕过它,除非使用 Win32 API 手动终止线程,这肯定 不会 是干净的。但是,如果这个第三方库没有为您提供任何其他选项,则可能需要这样做。 TerminateThread 函数是您想要使用的,但请注意警告!要获取要传递给此函数的线程 ID,您必须使用另一个 Win32 API 调用(Thread 类不直接公开它)。这里的做法是在托管线程方法开始时将一个 volatile 类变量的值设置为 GetCurrentThreadId 的结果,然后稍后使用这个线程 ID 来终止线程。

    【讨论】:

      【解决方案3】:

      不确定这是否可行或是否可以接受,但值得一试。

      [DllImport("kernel32.dll")]
      private static extern bool TerminateThread (Int32 id, Int32 dwexit);
      

      来自documentation

      TerminateThread 是一个危险的函数,只能在最极端的情况下使用。仅当您确切知道目标线程在做什么时才应该调用 TerminateThread,并且您可以控制目标线程在终止时可能正在运行的所有代码。例如,TerminateThread 可能会导致以下问题:

      • 如果目标线程拥有临界区,则不会释放临界区。
      • 如果目标线程正在从堆中分配内存,则不会释放堆锁。
      • 如果目标线程在终止时正在执行某些 kernel32 调用,则线程进程的 kernel32 状态可能不一致。
      • 如果目标线程正在操作共享 DLL 的全局状态,则 DLL 的状态可能会被破坏,从而影响 DLL 的其他用户。

      【讨论】:

        【解决方案4】:

        托管线程不能直接停止本机线程。因此,如果调用在本机代码中被阻塞,那么您能做的最好的事情就是让托管线程检查,然后在它返回后终止。如果它永远不会返回,也许有一个带有超时的调用版本?

        如果没有,杀死线程(通过 win32)通常不是一个好主意...

        【讨论】:

        • 调用永远不会返回,这就是为什么我不得不人为地终止线程。
        【解决方案5】:

        无限期地等待线程(任何语言)都不是一个好的解决方案,尤其是在您进行外部调用时。始终使用带有超时的连接,或监视共享原子变量状态的自旋锁,直到它发生变化,或者您达到超时。我不是 C# 人,但这些都是可靠的并发实践。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多