Hangfire - 防止入队的同一工作的倍数

时间:2017-07-18 10:37:28

标签: c# asp.net hangfire

情景:

作业1 计划每5分钟运行一次,大约需要1分钟才能完成。

很多工作堆积如山,工作1 需要15分钟才能运行。

现在有三个作业1 同时处理 - 我不希望这样。

<小时/> 如果已将作业1 再次添加到队列中,该怎么办?

是否有Hangfire设置,或者我是否需要手动轮询作业状态?

6 个答案:

答案 0 :(得分:4)

听起来这可能是您可能感兴趣的内容: https://discuss.hangfire.io/t/job-reentrancy-avoidance-proposal/607/8

讨论是关于跳过将同时执行到已经运行的作业的作业。

答案 1 :(得分:4)

有点晚,但是我正在使用此类来防止重复的作业同时运行

public class SkipConcurrentExecutionAttribute : JobFilterAttribute, IServerFilter, IElectStateFilter
{
    private readonly int _timeoutSeconds;
    private const string DistributedLock = "DistributedLock";

    public SkipConcurrentExecutionAttribute(int timeOutSeconds)
    {
        if (timeOutSeconds < 0) throw new ArgumentException("Timeout argument value should be greater that zero.");
        this._timeoutSeconds = timeOutSeconds;
    }

    public void OnPerformed(PerformedContext filterContext)
    {
        if (!filterContext.Items.ContainsKey(DistributedLock))
            throw new InvalidOperationException("Can not release a distributed lock: it was not acquired.");

        var distributedLock = (IDisposable)filterContext.Items[DistributedLock];
        distributedLock?.Dispose();
    }



    public void OnPerforming(PerformingContext filterContext)
    {
        filterContext.WriteLine("Job Started");

        var resource = String.Format(
                           "{0}.{1}",
                          filterContext.BackgroundJob.Job.Type.FullName,
                          filterContext.BackgroundJob.Job.Method.Name);

        var timeOut = TimeSpan.FromSeconds(_timeoutSeconds);

        filterContext.WriteLine($"Waiting for running jobs to complete. (timeout: { _timeoutSeconds })");

        try
        {
            var distributedLock = filterContext.Connection.AcquireDistributedLock(resource, timeOut);
            filterContext.Items[DistributedLock] = distributedLock;
        }
        catch (Exception ex)
        {
            filterContext.WriteLine(ex);
            filterContext.WriteLine("Another job is already running, aborted.");
            filterContext.Canceled = true; 
        }

    }

    public void OnStateElection(ElectStateContext context)
    {
        //if (context.CandidateState as FailedState != null)
        //{

        //}
    }
}

希望有帮助,谢谢!

答案 2 :(得分:2)

有一个名为DisableConcurrentExecution的属性,可以防止同时运行同一类型的2个作业。

尽管如此,在您的情况下最好是检查任务是否运行并相应地跳过。

答案 3 :(得分:2)

您可以使用DisableConcurrentExecution属性来防止同时多次执行某个方法。只需将此属性放在方法上方 -

即可
[DisableConcurrentExecution(timeoutInSeconds: 10 * 60)]
public void Job1()
{
    // Metohd body
}

答案 4 :(得分:0)

没有时间阅读关于这个简单概念是否甚至退出框架的github讨论页面上的页面?

如果您想放弃尝试运行两次,如果它已经运行,您可以随时执行此操作(请注意,不会应用任何属性):

    private static bool _isRunningUpdateOrders;
    public void UpdateOrders()
    {
        try
        {
            if (_isRunningUpdateOrders)
            {
                return; 
            }

            _isRunningUpdateOrders = true;

            // Logic...

        }
        finally 
        {
            _isRunningCreateGen2Data = false;
        }
   }

答案 5 :(得分:0)

是的,可能如下:

            RecurringJob.AddOrUpdate(Environment.MachineName, () => MyJob(Environment.MachineName), Cron.HourInterval(2));

和MyJob应该这样定义:

    public void MyJob(string taskId)
    {
        if (!taskId.Equals(Environment.MachineName))
        {
            return;
        }
        //Do whatever you job should do.
    }