最近使用TimedJob来处理定时任务, 但是遇到很多坑
比如我新建了多个job,配置了不同的时间来执行,但是经常会出现只能运行其中一个或者2个,三个以上经常就会丢掉。
后面就想那就放一个job里,然后根据不同的job配置不同的时间来运行。
所以这个总的job就是一个控制中心,我设置成每分钟执行一次。然后根据设置的时间来判断要不要执行。
所以这个方法的局限性就是在于 只能定时的每天的几点几分的任务,而不能做那种interval的任务,就是每隔10分钟执行,这个还得再想下方法。至少现在的能满足功能。
1,
根据这个思路,我得将这些job抽象出来,他们应该都有一个执行的入口
public interface IJobExecute
{
void DoExecute(DateTime now);
}
2,还得有一个抽象方法来继承 Pomelo.AspNetCore.TimedJob的IJob类
public abstract class AbsJob : IJobExecute
{
/// <summary>
/// job的名称
/// </summary>
public abstract string JobName { get; }
/// <summary>
/// job触发的小时
/// </summary>
public abstract int TriggerHour { get; }
/// <summary>
/// job触发的分钟
/// </summary>
public abstract int TriggerMinute { get; }
public void DoExecute(DateTime now)
{
//如果和触发时间不相同,则退出
if (!(now.Hour == TriggerHour && now.Minute == TriggerMinute))
{
return;
}
//开始执行具体job的内容
Execute(now);
}
///
///
///
public abstract void Execute(DateTime now);
}
3,有个job控制中心来收集所有的job来处理,这个就是要基础TimedJob里的Job类
public class JobControl : Pomelo.AspNetCore.TimedJob.Job
{
private readonly IEnumerable<IJobExecute> _jobs;
public JobControl (IEnumerable<IJobExecute> jobs) {
_jobs = jobs;
}
/// <summary>
/// 每分钟运行一次
/// </summary>
[Invoke(Begin = "2023-2-20 9:00", Interval = 1000 * 60, SkipWhileExecuting = true)]
public void Execute()
{
DateTime now = DateTime.Now;
try
{
foreach (var job in _jobs)
{
job.DoExecute(now);
}
}
catch (Exception ex)
{
//log
}
}
}
4, 然后可以针对自己的功能建job
public class TestTimeJob : AbsJob
{
public override string JobName { get { return "TestTimeJob"; } }
public override int TriggerHour { get { return 16; } }
public override int TriggerMinute { get { return 40; } }
private readonly IYourService _yourService;
public RefreshRedisTimeJob(IYourService yourService)
{
_yourService= yourService;
}
public override void Execute(DateTime now)
{
_yourService.ToDoSth();
}
}
4, 在startup中ConfigureServices方法中, 得使用TimedJob, 并且得注入你的jobs, 这样第3步中的注入IEnumerable jobs 就可以自动获取到了。以后只要新建一个job 然后在startup中加上注入这个job的代码,就可以了。
services.AddSingleton<IJobExecute, Test1TimeJob>();
services.AddSingleton<IJobExecute, Test2TimeJob>();
services.AddSingleton<IJobExecute, Test3TimeJob>();
services.AddTimedJob();
5, 在Startup的Configure方法中得加:
app.UseTimedJob();