你如何处理挂断电话的线程?

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

我调用了Thread.Abort,但现在已经读过Thread.Abort仅在控件返回托管代码时才有效。 我观察到这是真的,因为线程永远不会中止,我现在已经坐在Thread.Join上十分钟了。 这个挂线怎么办? 我应该将引用置空并继续吗? 我想尽可能干净 –

您的第三方库中的此function没有超时取消function? 如果是这样,这是非常糟糕的设计。 这里不会有任何漂亮的解决方案,可以解决…

不幸的是,除了使用Win32 API手动杀死线程之外,你无法绕过它,这肯定不会很干净。 但是,如果此第三方库未向您提供任何其他选项,则可能需要执行此操作。 TerminateThreadfunction是您想要使用的function,但请遵守警告! 要获取传递给此函数的线程ID,您必须使用另一个Win32 API调用( Thread类不直接公开它)。 这里的方法是在托管线程方法的开头将volatile变量的值设置为GetCurrentThreadId的结果,然后稍后使用该线程ID来终止线程。

随机思考:我想知道你是否可以将第二个程序集编写为一个小型控制台exe来进行此通信…使用Process.Start启动它并通过文件系统或拦截stdout捕获结果。 然后,如果它挂起,你可以杀死进程。

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

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

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

从文档中

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

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

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

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

不是一个好的解决方案,可以无限期地等待一个线程(任何语言),特别是如果你正在进行外部呼叫。 始终使用具有超时的连接,或者使用自旋锁来监视共享primefaces变量的状态,直到它发生更改,或者达到超时。 我不是C#家伙,但这些都是合理的并发实践。