How to properly stop a multi-threaded .NET windows service?

后端 未结 7 1541
温柔的废话
温柔的废话 2020-12-24 02:11

I have a windows service written in C# that creates a truck load of threads and makes many network connections (WMI, SNMP, simple TCP, http). When attempting to stop the win

7条回答
  •  悲哀的现实
    2020-12-24 02:43

    Matt Davis is pretty complete.
    A few points; If you have a thread that runs forever (because it has has a near-infinite loop and a catch all) and your service 's job is to run that thread, you probably want it to be a foreground thread.

    Also, if any of your tasks are performing a longer operation such as a sproc call and so your Join timeout needs to be a little longer, you can actually asked the SCM for more time to shut down. See: https://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.requestadditionaltime(v=vs.110).aspx This can be useful in avoiding the dreaded "marked for deletion" status. The maximum is set in the registry, so I usually request the max expected time the thread usually shuts down in (and never more than 12s). See: what is the maximum time windows service wait to process stop request and how to request for additional time

    My code looks something like:

    private Thread _worker;       
    private readonly CancellationTokenSource _cts = new CancellationTokenSource(); 
    
    protected override void OnStart(string[] args)
    {
        _worker = new Thread(() => ProcessBatch(_cts.Token));
        _worker.Start();             
    }
    
    protected override void OnStop()
    {            
        RequestAdditionalTime(4000);
        _cts.Cancel();            
        if(_worker != null && _worker.IsAlive)
            if(!_worker.Join(3000))
                _worker.Abort(); 
    }
    
    private void ProcessBatch(CancellationToken cancelToken)
    {
       while (true)
       {
           try
           {
               if(cancelToken.IsCancellationRequested)
                    return;               
               // Do work
               if(cancelToken.IsCancellationRequested)
                    return;
               // Do more work
               if(cancelToken.IsCancellationRequested)
                    return;
               // Do even more work
           }
           catch(Exception ex)
           {
               // Log it
           }
       }
    }
    

提交回复
热议问题