You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Hangfire即发即弃任务队列仅在指定时段运行?

实现Hangfire队列仅在指定时段执行任务的方案

完全可以实现让alpha队列的任务仅在每日指定时段(如00:00-03:00)执行,以下是几种实用的实现方式:

方案一:全局任务过滤器自动推迟非时段任务

通过Hangfire的任务过滤器,在任务准备执行前检查当前时间,若不在允许时段则自动推迟到下一个时段执行,无需修改任务提交逻辑。

步骤1:实现时间限制过滤器

public class TimeRestrictionFilter : IElectStateFilter
{
    public void OnStateElection(ElectStateContext context)
    {
        // 仅处理待入队状态的任务
        if (context.CandidateState.Name != EnqueuedState.StateName) return;

        var now = DateTime.Now;
        // 定义允许执行的时间范围(00:00-03:00)
        var allowedStart = new TimeSpan(0, 0, 0);
        var allowedEnd = new TimeSpan(3, 0, 0);
        var currentTime = now.TimeOfDay;

        if (!(currentTime >= allowedStart && currentTime <= allowedEnd))
        {
            // 计算距离下一次允许时段的时间差
            var nextAllowedStartTime = now.Date.AddDays(1).Add(allowedStart);
            var delay = nextAllowedStartTime - now;

            // 将任务改为调度状态,推迟到下一个时段执行
            context.CandidateState = new ScheduledState(delay)
            {
                Reason = "当前不在允许执行时段,自动推迟到下一个时段"
            };
        }
    }
}

步骤2:注册全局过滤器

在Hangfire配置代码中添加这个过滤器:

GlobalJobFilters.Filters.Add(new TimeRestrictionFilter());

方案二:定时启停Alpha队列的Hangfire Server

通过定时任务控制处理alpha队列的Server仅在指定时段运行,非时段内Server完全停止,不会处理队列中的任务。

代码示例

// 启动处理默认队列的Server(如需保留其他队列处理)
app.UseHangfireServer();

// 用于存储alpha队列Server的实例
private static BackgroundJobServer _alphaQueueServer;

// 启动alpha队列Server的方法
public void StartAlphaQueueServer()
{
    if (_alphaQueueServer == null)
    {
        var alphaOptions = new BackgroundJobServerOptions
        {
            Queues = new[] { "alpha" }
        };
        _alphaQueueServer = new BackgroundJobServer(alphaOptions);
    }
}

// 停止alpha队列Server的方法
public void StopAlphaQueueServer()
{
    _alphaQueueServer?.Dispose();
    _alphaQueueServer = null;
}

// 在应用启动时添加定时启停任务
RecurringJob.AddOrUpdate(() => StartAlphaQueueServer(), "0 0 * * *"); // 每日00:00启动
RecurringJob.AddOrUpdate(() => StopAlphaQueueServer(), "0 3 * * *"); // 每日03:00停止

方案三:提交任务时判断时间,直接调度到指定时段

从任务提交的源头控制,若当前不在允许时段,则直接将任务调度到下一个时段,而非立即入队。

代码示例

public void QueueNotification(string email)
{
    var now = DateTime.Now;
    var allowedStart = new TimeSpan(0, 0, 0);
    var allowedEnd = new TimeSpan(3, 0, 0);
    var currentTime = now.TimeOfDay;

    if (currentTime >= allowedStart && currentTime <= allowedEnd)
    {
        // 时段内直接入队执行
        BackgroundJob.Enqueue<YourService>(x => x.SendNotification(email));
    }
    else
    {
        // 计算下一个允许时段的开始时间
        var nextRunTime = now.Date.AddDays(1).Add(allowedStart);
        // 调度到下一个时段执行
        BackgroundJob.Schedule<YourService>(x => x.SendNotification(email), nextRunTime);
    }
}

方案对比

  • 方案一:无需修改现有任务提交代码,全局管控所有alpha队列任务,适合已有多处任务提交逻辑的场景。
  • 方案二:非时段彻底停止队列处理,节省服务器资源,适合任务量较大、对资源占用敏感的场景。
  • 方案三:从源头控制任务执行时间,队列中不会堆积非时段任务,适合任务提交频率较低的场景。

内容的提问来源于stack exchange,提问作者Can

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:32:07