Skip to main content
 首页 » 编程设计

.net之如何正确停止多线程 .NET Windows 服务

2024年12月31日14sharpest

我有一个用 C# 编写的 Windows 服务,它创建大量线程并建立许多网络连接(WMI、SNMP、简单 TCP、http)。当尝试使用服务 MSC 管理单元停止 Windows 服务时,停止服务的调用返回相对较快,但该过程继续运行大约 30 秒左右。

主要问题是停止需要 30 多秒的原因可能是什么。我可以寻找什么以及如何寻找它?

第二个问题是为什么即使进程仍在运行,服务 msc 管理单元(服务 Controller )仍会返回。有没有办法让它只在进程实际被杀死时才返回?

这是服务的 OnStop 方法中的代码

protected override void OnStop() 
{ 
   //doing some tracing 
   //...... 
 
   //doing some minor single threaded cleanup here 
   //...... 
 
   base.OnStop(); 
 
   //doing some tracing here 
} 

编辑以响应线程清理答案

你们中的许多人回答说我应该跟踪我所有的线程然后清理它们。我不认为这是一种实用的方法。首先,我无法访问一个位置的所有托管线程。该软件非常大,包含不同的组件、项目,甚至可以创建线程的 3rd 方 dll。我无法在一个位置跟踪所有这些,或者有一个所有线程都检查的标志(即使我可以让所有线程检查一个标志,许多线程也会阻塞信号量之类的东西。当它们阻塞时,它们可以'不检查。我将不得不让他们等待超时,然后检查这个全局标志并再次等待)。

IsBackround 标志是一个有趣的检查。尽管如此,我怎样才能知道我是否有任何前台线程在运行?我将不得不检查创建线程的代码的每个部分。有没有其他方法,也许是一个可以帮助我找到这个的工具。

但最终,该过程确实停止了。似乎我只需要等待一些东西。但是,如果我在 OnStop 方法中等待 X 时间,则该过程大约需要 30 秒 + X 才能停止。无论我尝试做什么,在 OnStop 返回后,该过程似乎需要大约 30 秒(并不总是 30 秒,它可能会有所不同)才能真正停止。

请您参考如下方法:

停止服务的调用会在您的 OnStop() 立即返回。回调返回。根据您显示的内容,您的 OnStop()方法并没有做太多,这就解释了为什么它返回得这么快。

有几种方法可以让您的服务退出。

首先,您可以返工 OnStop()方法来通知所有线程关闭并在退出之前等待它们关闭。正如@DSO 建议的那样,您可以使用全局 bool 标志来执行此操作(确保将其标记为 volatile )。我通常使用 ManualResetEvent,但两者都可以。通知线程退出。然后加入具有某种超时期限的线程(我通常使用 3000 毫秒)。如果此时线程仍未退出,您可以调用 Abort()退出它们的方法。一般情况下,Abort()方法不受欢迎,但鉴于您的进程无论如何都会退出,这没什么大不了的。如果您始终有一个必须中止的线程,您可以重新设计该线程以更好地响应您的关闭信号。

其次,将您的主题标记为background线程(见 here 更多细节)。听起来您正在为线程使用 System.Threading.Thread 类,默认情况下它们是前台线程。这样做将确保线程不会阻止进程退出。如果您只执行托管代码,这将正常工作。如果您有一个线程正在等待非托管代码,我不确定设置 IsBackground 属性是否仍会导致线程在关闭时自动退出,即,您可能仍然需要修改线程模型以使该线程响应您的关机请求。