代码之家  ›  专栏  ›  技术社区  ›  Jeff LaFay

如何使一个双赢的服务长期运行线程

  •  3
  • Jeff LaFay  · 技术社区  · 14 年前

    我有一个win服务托管一些工作流(一个WorkflowApplication和一个WorkflowServiceHost),我需要保持长时间运行。因为OnStart()要求它完成并返回到操作系统,所以我有一个main方法在线程池中的另一个线程上激发。我的Onstart()主要如下所示

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

    所以我认为我实现了错误的线程,这是什么 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.");
    }
    

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

    是否有任何明显的可以更改的内容,以使工作流长期处于执行状态?while循环似乎有点太黑客化了(更不用说我不喜欢把线程拖太长时间了),我相信可能有更好的解决方案。

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

    我在事件日志中从.Net获得此异常:

    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()
    

    3 回复  |  直到 14 年前
        1
  •  4
  •   Adam Robinson    14 年前

    首先,对于长时间运行的线程,创建自己的线程 Thread ThreadPool

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

    但是,如果您不能(或不想)修改其他流程以支持向您的服务通知特定事件,那么您所拥有的基本上是正确的。不过,我鼓励你选择一个更合理的方法 Sleep 真正地

        2
  •  2
  •   Ed Power    14 年前

    我用运行很长时间的Windows服务解决了这个问题 OnStart() 启动 System.Timers.Timer ,并在计时器的 ElapsedEventHandler .

    OnStop() 方法停止计时器并终止任何活动的工作线程。

        3
  •  0
  •   Aren    14 年前