Worker Service 动态改变执行间隔

2024-04-16

我有一个为所有工人提供基类的工人服务,它接受IOptionsMonitor构造函数参数。该监视器包含带有执行间隔值的选项对象实例。问题是如何动态改变间隔,即使await Task.Delay(Interval);被称为?我的意思是如果Interval值设置为一天,并且之后Task.Delay被调用的方法会更改,例如,更改为一小时 - 我仍然需要等待一天,并且只有在下一次调用时才会更新延迟。如果该房产我如何取消当前的延迟并开始新的延迟Interval值已更新? 谢谢。

请参阅下面所附的代码:

public abstract class WorkerBase<TWorker, TWorkerOptions> : BackgroundService
    where TWorker : WorkerBase<TWorker, TWorkerOptions>
    where TWorkerOptions : IHaveIntervalProperty
{
    protected WorkerBase(IServiceProvider serviceProvider, ILogger<TWorker> logger, IOptionsMonitor<TWorkerOptions> options)
    {
        _logger = logger;
        _serviceProvider = serviceProvider;
        _workerName = typeof(TWorker).Name;
        Interval = options.CurrentValue.Interval;
        options.OnChange(UpdateOptions);
    }

    public TimeSpan Interval { get; private set; }

    public virtual void UpdateOptions(TWorkerOptions options)
        => Interval = options.Interval;

    public abstract Task DoWork(IServiceProvider provider);

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation(Logs.InformationWorkerRunning, _workerName, DateTime.UtcNow);

            try
            {
                using var scope = _serviceProvider.CreateScope();
                await DoWork(scope.ServiceProvider);
            }
            catch (Exception e)
            {
                _logger.LogCritical(e, e.Message);
            }
            finally
            {
                await Task.Delay(Interval, stoppingToken);
            }
        }
    }
}

好的,根据 @Panagiotis Kanavos 的评论,我想出了以下代码:

public abstract class RepeatableWorker<TWorker, TOptions> : IHostedService, IDisposable
    where TWorker : RepeatableWorker<TWorker, TOptions>
    where TOptions : IHaveIntervalProperty
{
    #region Fields
    private readonly IServiceProvider _serviceProvider;
    private protected readonly ILogger<TWorker> _logger;
    private readonly string _workerName;
    private Timer? _executionTimer;
    private TimeSpan _interval;
    #endregion

    #region Constructors
    protected RepeatableWorker(IServiceProvider serviceProvider,
                               ILogger<TWorker> logger,
                               IOptionsMonitor<TOptions> options)
    {
        _serviceProvider = serviceProvider;
        _logger = logger;
        _workerName = typeof(TWorker).Name;
        _interval = options.CurrentValue.Interval;
        options.OnChange(UpdateOptions);
    }
    #endregion

    #region Properties
    public TimeSpan Interval
    {
        get => _interval;
        private set
        {
            if (value != _interval)
            {
                _executionTimer?.Change(TimeSpan.Zero, value);
                _interval = value;
            }
        }
    }
    #endregion

    #region Public methods
    public virtual void UpdateOptions(TOptions options)
        => Interval = options.Interval;

    public abstract void DoWork(IServiceProvider serviceProvider);

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation(Logs.InformationWorkerStarting, _workerName, DateTime.UtcNow);
        _executionTimer = new(DoWorkInternal, null, TimeSpan.Zero, Interval);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation(Logs.InformationWorkerStopping, _workerName, DateTime.UtcNow);
        _executionTimer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        GC.SuppressFinalize(this);

        _executionTimer?.Dispose();
    }
    #endregion

    #region Private methods
    private void DoWorkInternal(object? state)
    {
        try
        {
            _logger.LogInformation("Worker {0} running at {1}.", _workerName, DateTime.UtcNow);
            using var scope = _serviceProvider.CreateScope();
            DoWork(scope.ServiceProvider);
        }
        catch (Exception e)
        {
            _logger.LogCritical(e, e.Message);
        }
    }
    #endregion
}

And the IHaveIntervalProperty界面:

public interface IHaveIntervalProperty
{
    TimeSpan Interval { get; set; }
}

以防万一有人需要这样的解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Worker Service 动态改变执行间隔 的相关文章

随机推荐

  • 在 AngularJS 的 ng-bind 中使用过滤器后添加更多文本

    所以我想在 ng bind 指令中通过过滤器放置一个变量 ng bind input filter 但我想插入更多文字 ng bind input filter more 但这不起作用 有没有办法在 ng bind 中添加更多文本 就像您简
  • CMake子目录依赖

    我对 CMake 很陌生 事实上 我正在通过 Kdevelop4 widh C 进行尝试 我习惯为我创建的每个命名空间创建子目录 即使所有源代码都必须编译并链接到单个可执行文件中 好吧 当我在 kdevelop 下创建一个目录时 它会使用
  • Chart.js - 如何禁用悬停时的所有内容

    如何设置代码使图表上没有悬停效果 悬停选项 悬停 链接等 我正在使用 Chart js 下面是我的代码 我在其中设置饼图 Html div style width 90 div
  • 锁定安卓手机

    当用户按下按钮时 我试图以编程方式锁定设备 我知道我需要使用deviceAdminReciever我已经这样做了 但是每当我运行它时我的应用程序就会崩溃 以下是我的清单
  • 为什么 IE8 使用 Facebook 的 React.js 时会出现脚本错误

    我正在使用 Facebook 反应 不确定是什么导致了这个错误 似乎是反应本身 我收到 IE8 脚本错误 React js 的第 10898 行对象不支持此属性或方法 我没有使用缩小版本 这是带注释的开发版本 还有人遇到 facebook
  • 如何获取受 SQLAlchemy 影响的行数?

    如何使用 sqlalchemy 获取更新语句影响的行数 我正在使用 mysql 和 python pyramid from sqlalchemy engine base import ResultProxy classmethod def
  • 在命名空间中包装 extern“C”库时出现问题

    我正在使用 C 中的 C 库 libgretl 它的一些函数与我的代码冲突 所以我想将它包装在命名空间中 如下所示 namespace libgretl extern C include
  • 在没有 unsafeCoerce 的情况下兼顾存在主义

    最近我一直在研究这种类型 我理解它是自由分配函子的编码 有关切线背景 请参阅这个答案 https stackoverflow com a 56822105 2751851 data Ev g a where Ev g x gt x gt a
  • 作为服务在 Heroku 或其他云平台上进行蓝绿部署

    我们目前正在 Heroku 上使用两个测功机运行 Ruby on Rails 项目 RefineryCMS 每次更新网站时 我们都会遇到大约 1 到 2 分钟的停机时间 管理层对此并不满意 我们真正想要的是某种 透明的 蓝绿部署 http
  • 使用 requirejs 调用函数

    如何使用 requirejs 调用函数 这是一个过于简单的问题 但令人惊讶的是 到目前为止没有任何教程或示例能够帮助我 这是我的 html 文件中的代码
  • git 仅克隆具有特定扩展名的文件

    有没有办法只克隆具有特定扩展名的文件 例如 只克隆 sh 文件 我知道我可以克隆整个文件 然后删除剩余的文件 但我不想浪费 谢谢 None
  • AWS Lambda 的打包代码

    我正在尝试打包 AWS Lambda 的代码 Lambda 有各种限制 例如使用 Node 6 10 并且没有像 AWS EB 那样的构建步骤 我还使用 NPM 模块 因此这些模块需要与 AWS Lambda 处理程序捆绑在一起 这是我想做
  • SetVisible(false) 更改面板中组件的布局

    当我将子面板之一设置为不可见时 如何使主面板中的子面板保持在原来的位置 我所拥有的看起来像 Panel1 Panel2 Panel3 Panel4 当我做panel3 setVisible false 它看起来像 Panel1 Panel2
  • Bootstrap 3 - 如何在单击时淡入警报框并在 3 秒后淡出

    我正在使用 AngularJS 和 Bootstrap 3 我的 Web 应用程序有一个 更新 按钮 用于保存用户所做的任何更改 当用户单击 更新 按钮时 我想激活并淡入引导程序的警报框 显示 信息已保存 然后在 3 秒后淡出 我不知道如何
  • 如何在 javascript google 地图 API 上使用米显示 geojson 数据

    GeoJson 文件坐标以 X Y 米为单位 而不是 lng lat 如何在谷歌地图上显示 GeoJson数据 type FeatureCollection features type Feature geometry type Multi
  • Keycloak 中的多租户可以在单个领域内完成吗?

    首先 我非常了解 Keycloak 中的多领域多租户方法 我接手了一个遗留项目 没有人想到多租户 现在 两年后 客户突然需要此功能 实际上 微服务已经为这种场景做好了开箱即用的准备 客户开发了一个移动应用程序 通过我们的 keycloak
  • 在arcore中的3D对象上使用模板蒙版时出现问题

    我正在使用 hello ar java demo 在 3d 对象上使用模板掩模 但是我遇到了一些意外的行为 我的模板蒙版正确遮挡了平面渲染器 但 3D 对象 andy 似乎没有按预期做出反应 相反 如图所示 他似乎被翻转了 我不知道如何解决
  • 如何在android中创建圆角videoview?

    In my application I want to display videoview as a rounded corners I have tried placing videoview surfaceview inside lin
  • ngModel 中的异步数据

    我有带有异步数据的表单
  • Worker Service 动态改变执行间隔

    我有一个为所有工人提供基类的工人服务 它接受IOptionsMonitor构造函数参数 该监视器包含带有执行间隔值的选项对象实例 问题是如何动态改变间隔 即使await Task Delay Interval 被称为 我的意思是如果Inte