如何确保在 Windows 服务上完成小型工作单元作业 停止或关闭



我有一个每 X 秒运行一次的作业,在 WindowsService 中运行该作业的执行时间不应长(少于 5 秒)。我的目标是确保当前正在运行的作业在 Windows 服务在执行过程中停止时完成其执行。

这个线程看起来很有趣,但到目前为止它不起作用:应用程序关闭时的任务处理

任何帮助将不胜感激。

WindowsService 实现:

public partial class WindowsService : ServiceBase
{
    private readonly ILogger logger;
    private readonly IStartJob startJob;
    private readonly CancellationTokenSource cancellationTokenSource;
    private Task task;
    public WindowsService(IStartJob startJob, ILogger logger)
    {
        // Dependancy injection of logger and JobStarter
        this.startJob = startJob;
        this.logger = logger;
        InitializeComponent();
        cancellationTokenSource = new CancellationTokenSource();
    }
    protected override void OnStart(string[] args)
    {
        task = new Task(() => startJob.Start(cancellationTokenSource.Token), 
            cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
        task.Start();
        logger.Info("Service started");
    }
    protected override void OnStop()
    {
        RequestAdditionalTime(TimeSpan.FromSeconds(30).Milliseconds);
        cancellationTokenSource.Cancel();
        try { task.Wait(); }
        catch (Exception ex) { logger.Error("Error while stopping the Service", ex); }
        logger.Info("Service stopped");
    }
}

启动作业实现:

public class StartJob : IStartJob
{
    private readonly ILogger logger;
    private readonly IExecuteJob executeJob;
    private DateTime lastExecution = DateTime.UtcNow.AddDays(-1);
    public StartJob(ILogger logger, IExecuteJob executeJob)
    {
        this.logger = logger;
        this.executeJob = executeJob;
    }
    public async void Start(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            var nextExecution = lastExecution.AddSeconds(5);
            if (nextExecution < DateTime.UtcNow)
            {
                try
                {
                    logger.Info("Start Job Execution");
// To similate long process not ended, break point here
// and stop the service before continuing the execution.
                    Thread.Sleep(5000);
                    executeJob.Execute();   
                    logger.Info("Job completed");
                    AdjustLastExecution(nextExecution);
                }
                catch (Exception ex)
                {
                    logger.Error("Unexpected exception while executing job", ex);
                }
            }
// Would expect the cancelToken to activate here or in the while condition
            await Task.Delay(TimeSpan.FromSeconds(1), token);
        }
    }
    private void AdjustLastExecution(DateTime nextExecution)
    {
        // To ensure we have an heartbeat close to 5 seconds
        lastExecution = nextExecution.AddSeconds(5) > DateTime.UtcNow  ?
            nextExecution : DateTime.UtcNow.AddSeconds(-5);
    }
}

我尝试了一堆变体,输入任务中存在的 cancelToken,任务等待和等待毫秒超时,但到目前为止没有任何效果。

我将我的解决方案附加到正在执行的 WindowsService,并确保正在执行的作业将位于其中的中间,其中包含断点和 Thread.Sleep。但是,不会写入作业已完成日志,并且在其之前会删除附加的已处理日志。

我很快看了你的代码,我唯一会尝试的是

替换 :

async void

async Task

我不保证它适用于您的情况,但我记得阅读这篇文章建议避免异步无效

在 C# 中,异步 void 方法是代码的祸害。

Haacked.com |避免异步无效方法

编辑:

task = new Task(() => startJob.Start(cancellationTokenSource.Token), 
        cancellationTokenSource.Token, TaskCreationOptions.LongRunning);

task = startJob.Start(cancellationTokenSource.Token);

最新更新