无需中止或暂停即可终止无环线程

时间:2012-04-03 16:50:48

标签: c# multithreading tcpclient terminate suspend

我正在实现一个协议库。这是一个简化的描述。

主函数中的主线程将始终检查网络流上是否有某些数据(在tcpclient中)。让我们说响应是收到的消息,而线程是一个正在运行的线程。

thread = new Thread(new ThreadStart(function));
thread.IsBackground = true;
thread.Start();

while(true){

response = receiveMessage();

if (response != null)
     {                
      thread.Suspend();
      //I am searching for an alternative for the line above and not thread.Abort().

      thread2 = new Thread(new ThreadStart(function2));
      thread2.IsBackground = true;
      thread2.Start();         
     }
}

到目前为止,在while循环中实际上有更多的消息,并且还有一个用于处理不同类型的传入消息的状态机,但这应该足够了。 (还有不仅仅是函数“function”和“function2”)。

所以无论如何这些函数在这个应用程序中看起来都不清楚,因为协议是程序员隐藏的并且意味着是一个库。这意味着协议将启动一些程序员定义的函数作为线程,具体取决于程序在协议中的状态。

因此,如果接收到特殊响应(例如callAnotherFunction消息),我想终止 一个线程(这里名为“thread”)突然间,让我们说在100毫秒内。但是我不知道它是在一个循环内执行还是没有执行,在它终止之前需要多少处理。

如何在不弃用Suspend或Exceptionthrowing Abort函数的情况下停止这些线程? (注意,我不能强制函数的程序员捕获ThreadAbortException。)

或者我需要不同的程序架构? (顺便说一下,我决定将循环放在receiveMessage中,以便将网络流轮询到主函数中,因为任何时候都可以出现消息)。

4 个答案:

答案 0 :(得分:4)

在没有可靠的方法终止它的情况下启动一个线程是一种不好的做法。 Suspend / Abort是终止线程的不可靠方法之一,因为你可能会终止一个破坏整个程序的状态的线程,而你无法避免它发生。

您可以在此处查看如何安全地杀死线程:Killing a .NET thread

如果“user”为您提供了在线程中运行的方法,那么用户还应该为您提供一种方法来阻止代码运行。将其视为合同:您向用户保证将调用stop方法,并且他们承诺stop方法将实际停止该线程。如果您的用户违反了该合同,那么他们将对出现的问题负责,这很好,因为您不想对用户的错误负责:)。

  

请注意,我不能强制函数的程序员捕获ThreadAbortException。

由于暂停/中止是不好的做法,程序员不需要捕获ThreadAbortException,但是他们应该将ThreadInterruptedException作为他们“合同”的一部分。

请记住,您需要担心两种情况:

  1. 线程正在执行一些代码。
  2. 线程处于阻塞状态。
  3. 在线程正在执行某些代码的情况下,您所能做的就是通知线程它可以退出并等待它处理通知。您也可以跳过等待并假设您泄漏了资源,在这种情况下,再次出现用户的错误,因为他们没有设计停止方法来及时终止其线程。

    如果线程处于阻塞状态并且它没有阻塞通知构造(即信号量,手动重置事件等),那么您应该调用Thread.Interrupt()以使其脱离阻塞状态 - 用户必须处理ThreadInterruptedException

答案 1 :(得分:1)

暂停真的很邪恶,特别是在你试图使用它的方式 - 永远停止线程执行。它会留下线程拥有的所有锁,也不会释放资源。

线程中止稍微好一些,因为它至少会尝试终止线程清理程序,锁定将有机会被释放。

要正确地做到这一点,你真的需要你的线程代码在终止时合作。线程检查的事件,信号量甚至简单的bool值都可能就足够了。

最好重新构建解决方案以获取消息队列并在单独的线程上处理它们。特殊消息可能只是清空队列。

答案 2 :(得分:1)

您需要在应用程序和function来自的任何地方之间使用某种取消协议。然后,您可以在function和消息循环之间共享某种取消令牌。如果消息循环识别出需要停止function,则通过设置必须在适当的时候通过函数测试的令牌来发出信号。最简单的方法是共享一个条件变量,该变量可以在消息循环中以原子方式设置,并从function原子读取。

然而,我会考虑使用正确的异步IO模式与.NET框架提供的Tasks开箱即用,以及正确的取消机制。

答案 3 :(得分:1)

所以function是指您无法控制的代码?这是第三方图书馆的典型特征。大多数情况下,他们没有内置的能力来优雅地终止长时间运行的操作。由于您不知道如何实现这些功能,因此您只有很少的选择。事实上,您唯一可靠的安全选择是在自己的进程中启动这些操作,并通过WCF与它们进行通信。这样,如果你需要突然终止操作,你就会杀死进程。杀死另一个进程不会破坏当前进程的状态,就像在当前进程中调用线程Thread.Abort时会发生的情况一样。