如何确保由Windows服务定时器产生的线程在停止Windows服务后完成执行

本文关键字:Windows 服务 线程 执行 何确保 确保 定时器 | 更新日期: 2023-09-27 18:09:45

我正在使用System.Timers.Timer构建Windows服务。计时器委托计算的任务可能需要几秒到几分钟。我想确保,当服务停止时,所有当前运行的委托线程在被处置之前都已完成。

这是代码,但是它没有做我所期望的,因为当前正在运行的线程永远不会完成,如果Windows服务在运行时停止。

public abstract class AgentServiceBase : ServiceBase
{
    private System.ComponentModel.IContainer components = null;
    private System.Timers.Timer _Timer;
    private string _logPath;
    private const int MAXNUMBEROFTHREADS = 10;
    protected int interval = 25000;
    protected int numberOfAllowedThreads = 2;
    public AgentServiceBase()
    {
        this.InitializeComponent();
        this._logPath = (Path.GetDirectoryName(Assembly.GetAssembly(this.GetType()).CodeBase)).Substring(6).Replace("/", @"'");
    }
    protected override void OnStart(string[] args)
    {
        if (args.Length > 0)
        {
            int.TryParse(args[0], out interval);
        }
        if (args.Length > 1)
        {
            int.TryParse(args[1], out numberOfAllowedThreads);
            if (numberOfAllowedThreads > MAXNUMBEROFTHREADS)
            {
                numberOfAllowedThreads = MAXNUMBEROFTHREADS;
            }
            if (numberOfAllowedThreads == 1)
            {
                numberOfAllowedThreads = 2;
            }
        }
        ThreadPool.SetMaxThreads(numberOfAllowedThreads, numberOfAllowedThreads);
        this._Timer = new System.Timers.Timer();
        this._Timer.Elapsed += new ElapsedEventHandler(PollWrapper);
        this._Timer.Interval = this.interval;
        this._Timer.Enabled = true;
    }
    protected override void OnStop()
    {
        this._Timer.Enabled = false;
        Process currentProcess = Process.GetCurrentProcess();
        foreach (Thread t in currentProcess.Threads)
        {
            t.Join();
        }
    }
    /// <summary>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    private void InitializeComponent()
    {
        components = new System.ComponentModel.Container();
        this.ServiceName = "Agent Service - Johnhenry";
    }
    private void PollWrapper(object sender, ElapsedEventArgs e)
    {
        try
        {
            this.Poll(sender, e);
        }
        catch (Exception exception)
        {
            string message = this.GetType().FullName + "  - Windows Service Exception'n";
            message += exception.GetNestedExceptionInSingleStringOutput();
            FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
        }
    }
    protected abstract void Poll(object sender, ElapsedEventArgs e);
}
许多谢谢,

朱塞佩

:

经过几次不同的尝试,计数当前进程自己的线程,我最终解决了一个更简单的解决方案,即使用计时器已经启动的线程计数器,仍在运行。基于此,我在主线程上调用Sleep并发出RequestAdditionalTime,直到所有线程都结束。以下是修订后的2种方法:

    protected override void OnStop()
    {
        this._Timer.Enabled = false;
        while (numberOfRunningThreads > 0)
        {
            this.RequestAdditionalTime(1000);
            Thread.Sleep(1000);
        }
    }

    private void PollWrapper(object sender, ElapsedEventArgs e)
    {
        numberOfRunningThreads++;
        try
        {
            this.Poll(sender, e);
        }
        catch (Exception exception)
        {
            string message = this.GetType().FullName + "  - Windows Service Exception'n";
            message += exception.GetNestedExceptionInSingleStringOutput();
            FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
        }
        finally
        {
            numberOfRunningThreads--;
        }
    }

如何确保由Windows服务定时器产生的线程在停止Windows服务后完成执行

你可以通过调用RequestAdditionalTime来实现,只要你的线程还没有完成在循环内实现OnStop的工作(在调用Join()之前和/或之后)。

但要注意, Windows可能会失去耐心,决定杀死你的Windows服务-例如在关机期间…

有关详细信息,请参阅MSDN参考:http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.aspx