如何使Win服务长期运行线程

我有一个win服务托管一些我需要长时间运行的工作流程(WorkflowApplication和WorkflowServiceHost)。 因为OnStart()要求它完成并返回到操作系统,所以我有一个主方法可以触发线程池中的另一个线程。 我的Onstart()主要看起来像这样

protected override void OnStart(string[] args) { eventLog.WriteEntry("Service starting..."); ThreadPool.QueueUserWorkItem(new WaitCallback(ServiceMainThread)); Thread.Sleep(100); eventLogCms.WriteEntry("Service Started."); } 

ServiceMainThread()是我的工作流程执行和实现核心function的方法。 当我在Windows 7机器上启动服务时,它运行然后在大约8分钟后死亡。 在Win Server 2008上,线程永远不会执行。

所以我认为我已经错误地实现了线程,而且什么是ServiceMainThread有点不对劲。 我愿意接受有关可以改进的建议或任何方向的建议,因为我刚接触线程.Net。 ServiceMainThread中的基本线程代码编码如下:

 private void ServiceMainThread(object state) { // .. execute workflows .. eventLog.WriteEntry("Workflows executed."); while(alive) { Thread.Sleep(1); // ... check workflow states and ensure they're still executing ... } // .. halt workflow executions and perform persist operations if necessary .. eventLog.WriteEntry("Workflows halted."); } 

为了充分说明的目的,这里是我的OnStop()实现:

 protected override void OnStop() { alive = false; this.haltEvent.WaitOne(); // haltEvent is of type ManualResetEvent } 

是否有任何明显的变化可以让我的工作流程长期保持在执行状态? while循环似乎有些过于hackish(更不用说我不喜欢在任何时间内延迟线程)并且我确信可能有更好的解决方案。

使用线程而不是线程池确实可以启动,但它似乎允许工作流在执行开始前运行2分钟,现在停止了,但我想我可能能够纠正OnStop()。 当我这样做时,我将ServiceMainThread()中的while循环设置为空块,因此它不会阻止工作流正在执行的线程。

更新:我在事件日志中从.Net获得此exception:

 Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.NullReferenceException Stack: at Ptm.ServiceMainThread() at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) at System.Threading.ThreadHelper.ThreadStart() 

Server 2008是64位,可能与我的问题有关吗?

首先,对于长时间运行的线程,创建自己的Thread对象并启动它; 不要使用ThreadPool 。 线程池专为小型,相对短期的操作而设计。

其次,有几种方法可以让你的线程保持活力。 最基本的是你尝试过的,这是一个while循环,最后有一个sleep(或其他阻塞)调用。 这是最基本的,但不一定是“最好的”。 还有其他选项,例如可以从其他应用程序访问的名为WaitHandle对象,可以允许更确定的代码执行和更少的唤醒 – 检查 – 睡眠迭代。

但是,如果您不能(或不想)修改其他流程以支持通知您的服务特定事件,那么您所拥有的基本上是正确的。 但是,我会鼓励选择更合理的Sleep时间; 你真的需要检查每毫秒吗?

我通过让OnStart()启动System.Timers.Timer来解决我长时间运行的Windows服务的问题,并在计时器的ElapsedEventHandler执行所有处理。

在处理程序内部,我停止计时器,在单独的线程上执行工作,检查暂停信号,然后重新启动计时器,如果可以继续。 该服务的OnStop()方法停止计时器并杀死任何活动的工作线程。

工作线程处理所有exception,因此如果有问题,它会记录exception,终止,然后在下一个计时器间隔重新启动。 服务核心从未崩溃过。

关于阻塞,你应该使用等待/脉冲编程范例来发信号通知一个线程继续。 或者只是加入线程。

Wait&Pulse – C#中的线程