我正在使用.NET 3.5,并试图解决一个问题(不是我的最高线程专家)。
我有一个Windows服务,它有一个非常密集的进程,一直在运行,我把这个进程放到一个单独的线程上,以便我的服务的主线程可以处理操作任务 - 即服务审计周期,处理配置更改等等。
我通过典型的ThreadStart启动线程到一个关闭进程的方法 - 称之为workerthread。
在这个workerthread上我将数据发送到另一台服务器,正如预期的那样,服务器不时重新启动并且连接丢失,我需要重新建立连接(我通过事件丢失连接通知我) 。从这里开始我的重新连接逻辑,我重新开始运行,但是我很容易注意到的是,我每次都在反复创建这个工作线程(不是我想要的)。
现在,当我失去连接并开始新的连接时,我可以杀死它,但这似乎浪费了资源。
我真正想要做的是,将调用(即我的线程启动方法)编组回到仍在内存中的线程,尽管没有做任何事情。
请发布您有用的任何示例或文档。
感谢。
答案 0 :(得分:3)
你应该避免杀死工作线程。当您强制终止Win32线程时,并非所有资源都已完全恢复。我相信当Win32线程被杀死时,线程堆栈的保留虚拟地址空间(或者它是根页?)不会被恢复。它可能不会太多,但在长期运行的服务器服务流程中,它会随着时间的推移而累积,最终会降低您的服务。
如果允许线程退出其threadproc以正常终止,则恢复所有资源。
如果后台线程将连续运行(不休眠),您可以使用全局布尔标志来在主线程和后台线程之间传递状态。只要后台线程定期检查此全局标志。如果设置了标志,则线程可以干净地关闭并退出。如果主线程是唯一的编写器而后台线程只读取标志值,则不需要锁定语义。
当后台线程丢失与发送数据的服务器的连接时,为什么不自行执行重新连接?我不清楚为什么主线程需要拆除后台线程来启动另一个线程。
答案 1 :(得分:1)
无论如何,我会杀死(但如果可能的话,优雅地结束)工作线程。一切都被垃圾收集,你可以从头开始。
此服务器重启的频率是多少?如果它经常发生,资源成为一个问题,它可能经常发生。
答案 2 :(得分:1)
您可以使用Singleton模式。在您的情况下,使连接成为静态对象。两个线程都可以访问该对象,这意味着构造并使用它。
主线程可以在需要时构造它,并且只要可用,工作线程就会访问它。
答案 3 :(得分:1)
使用ThreadPool.QueueUserWorkItem
来调用方法。此方法从线程池中获取一个线程并启动一个方法。它似乎是在另一个线程上启动方法的任务的理想选择。
此外,当您说“典型的ThreadStart”时,您的意思是说您正在使用Thread
参数创建并启动新的ThreadStart
,或者您正在创建ThreadStart
并致电Invoke
就可以了?
答案 4 :(得分:1)
您考虑过BackgroundWorker吗?
根据我的理解,你只需要一个正在工作的线程,除非你需要cancel处理它。
答案 5 :(得分:1)
BackgroundWorker比使用普通线程慢一点,但它可以选择支持CancelAsync方法。
基本上,BackgroundWorker
是工作线程的包装器,带有一些额外的选项和事件。
CancelAsync
方法仅在设置WorkerSupportsCancellation时有效
调用CancelAsync
时,会设置CancellationPending
工作者线程应定期检查CancellationPending
以确定是否需要提前退出。
- 的Jeroen