using NCC.Dependency;
using NCC.IPCChannel;
using NCC.Templates.Extensions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
namespace NCC.TaskScheduler
{
///
/// 后台任务静态类
///
[SuppressSniffer]
public static class SpareTime
{
///
/// 开始执行简单任务(持续的)
///
/// 时间间隔(毫秒)
///
///
///
///
///
///
public static void Do(double interval, Action doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
Do(() => interval, doWhat, workerName, description, startNow, cancelInNoneNextTime, executeType, true);
}
///
/// 开始执行简单任务(持续的)
///
/// 时间间隔(毫秒)
///
///
///
///
///
///
/// 无关紧要的参数(用于检查器,外部不可用)
public static void Do(double interval, Func doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel, bool onlyInspect = false)
{
Do(() => interval, doWhat, workerName, description, startNow, cancelInNoneNextTime, executeType, true, onlyInspect);
}
///
/// 模拟后台执行任务
/// 10毫秒后执行
///
///
///
///
///
public static void DoIt(Action doWhat = default, double interval = 30, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
if (doWhat == null) return;
DoOnce(interval, (_, _) => doWhat(), cancelInNoneNextTime: cancelInNoneNextTime, executeType: executeType);
}
///
/// 模拟后台执行任务
/// 10毫秒后执行
///
///
///
///
///
public static void DoIt(Func doWhat = default, double interval = 30, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
if (doWhat == null) return;
DoOnce(interval, async (_, _) => await doWhat(), cancelInNoneNextTime: cancelInNoneNextTime, executeType: executeType);
}
///
/// 开始执行简单任务(只执行一次)
///
/// 时间间隔(毫秒)
///
///
///
///
///
///
public static void DoOnce(double interval, Action doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
Do(() => interval, doWhat, workerName, description, startNow, cancelInNoneNextTime, executeType, false);
}
///
/// 开始执行简单任务(只执行一次)
///
/// 时间间隔(毫秒)
///
///
///
///
///
///
public static void DoOnce(double interval, Func doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
Do(() => interval, doWhat, workerName, description, startNow, cancelInNoneNextTime, executeType, false);
}
///
/// 开始执行 Cron 表达式任务
///
/// Cron 表达式
///
///
///
///
///
/// 配置 Cron 表达式格式化
///
public static void Do(string expression, Action doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, CronFormat? cronFormat = default, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
Do(() => GetCronNextOccurrence(expression, cronFormat), doWhat, workerName, description, startNow, cancelInNoneNextTime, executeType);
}
///
/// 开始执行 Cron 表达式任务
///
/// Cron 表达式
///
///
///
///
///
/// 配置 Cron 表达式格式化
///
public static void Do(string expression, Func doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, CronFormat? cronFormat = default, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
Do(() => GetCronNextOccurrence(expression, cronFormat), doWhat, workerName, description, startNow, cancelInNoneNextTime, executeType);
}
///
/// 开始执行下一发生时间任务
///
/// 返回下一次执行时间
///
///
///
///
/// 在下一个空时间取消任务
///
public static void Do(Func nextTimeHandler, Action doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
Do(nextTimeHandler, async (s, i) =>
{
doWhat(s, i);
await Task.CompletedTask;
}, workerName, description, startNow, cancelInNoneNextTime, executeType);
}
///
/// 开始执行下一发生时间任务
///
/// 返回下一次执行时间
///
///
///
///
/// 在下一个空时间取消任务
///
public static void Do(Func nextTimeHandler, Func doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel)
{
if (doWhat == null) return;
// 每 30ms 检查一次
Do(30, async (timer, tally) =>
{
// 获取下一个执行的时间
var nextLocalTime = nextTimeHandler();
// 判断是否在下一个空时间取消任务
if (cancelInNoneNextTime)
{
if (nextLocalTime == null)
{
Cancel(workerName);
return;
}
}
else
{
if (nextLocalTime == null) return;
}
// 获取当前任务的记录
_ = WorkerRecords.TryGetValue(workerName, out var currentRecord);
// 更新任务信息
currentRecord.Timer.Type = timer.Type = SpareTimeTypes.Cron;
currentRecord.Timer.Status = timer.Status = SpareTimeStatus.Running;
currentRecord.Timer.Tally = timer.Tally = currentRecord.CronActualTally;
// 只有时间相等才触发
var interval = (nextLocalTime.Value - DateTimeOffset.UtcNow.ToLocalTime()).TotalMilliseconds;
var x = Math.Round(Math.Round(interval, 3, MidpointRounding.ToEven));
if (x > 30)
{
UpdateWorkerRecord(workerName, currentRecord);
return;
}
// 延迟 100ms 后执行,解决零点问题
await Task.Delay(100);
// 更新实际执行次数
currentRecord.Timer.Tally = timer.Tally = currentRecord.CronActualTally += 1;
UpdateWorkerRecord(workerName, currentRecord);
// 执行前通知
await WriteChannel(timer, 1);
// 执行方法
await doWhat(timer, currentRecord.CronActualTally);
// 执行后通知
await WriteChannel(timer, 2);
}, workerName, description, startNow, cancelInNoneNextTime, executeType, true);
}
///
/// 开始执行简单任务
///
/// 时间间隔(毫秒)
///
///
///
///
///
///
/// 是否持续执行
public static void Do(Func intervalHandler, Action doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel, bool continued = true)
{
Do(intervalHandler, async (s, i) =>
{
doWhat(s, i);
await Task.CompletedTask;
}, workerName, description, startNow, cancelInNoneNextTime, executeType, continued);
}
///
/// 开始执行简单任务
///
/// 时间间隔(毫秒)
///
///
///
///
///
///
/// 是否持续执行
/// 无关紧要的参数(用于检查器,外部不可用)
public static void Do(Func intervalHandler, Func doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel, bool continued = true, bool onlyInspect = false)
{
if (doWhat == null) return;
// 自动生成任务名称
workerName ??= Guid.NewGuid().ToString("N");
// 获取执行间隔
var interval = intervalHandler();
// 判断是否在下一个空时间取消任务
if (cancelInNoneNextTime)
{
if (interval <= 0)
{
Cancel(workerName);
return;
}
}
else
{
if (interval <= 0) return;
}
// 创建定时器
var timer = new SpareTimer(interval, workerName)
{
Type = SpareTimeTypes.Interval,
Description = description,
Status = startNow ? SpareTimeStatus.Running : SpareTimeStatus.Stopped,
ExecuteType = executeType
};
// 支持异步事件
Func