/// <summary> /// 开始执行简单任务(持续的) /// </summary> /// <param name="interval">时间间隔(毫秒)</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="executeType"></param> /// <param name="onlyInspect">无关紧要的参数(用于检查器,外部不可用)</param> /// public static void Do(double interval, Func <SpareTimer, long, Task> 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); }
/// <summary> /// 模拟后台执行任务 /// <para>10毫秒后执行</para> /// </summary> /// <param name="doWhat"></param> /// <param name="interval"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="executeType"></param> public static void DoIt(Func <Task> 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); }
/// <summary> /// 开始执行简单任务 /// </summary> /// <param name="intervalHandler">时间间隔(毫秒)</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="executeType"></param> /// <param name="continued">是否持续执行</param> /// <param name="onlyInspect">无关紧要的参数(用于检查器,外部不可用)</param> public static void Do(Func <double> intervalHandler, Func <SpareTimer, long, Task> 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 }; // 支持异步事件 async Task handler(object sender, ElapsedEventArgs e) { // 获取当前任务的记录 _ = WorkerRecords.TryGetValue(workerName, out var currentRecord); // 处理串行执行问题 if (timer.ExecuteType == SpareTimeExecuteTypes.Serial) { if (!currentRecord.IsCompleteOfPrev) { return; } // 立即更新多线程状态 currentRecord.IsCompleteOfPrev = false; UpdateWorkerRecord(workerName, currentRecord); } // 记录执行次数 if (timer.Type == SpareTimeTypes.Interval) { currentRecord.Timer.Tally = timer.Tally = currentRecord.Tally += 1; } // 处理多线程并发问题(重入问题) var interlocked = currentRecord.Interlocked; if (Interlocked.Exchange(ref interlocked, 1) == 0) { try { // 执行前通知 if (timer.Type == SpareTimeTypes.Interval && !onlyInspect) { await WriteChannel(timer, 1); } // 执行任务 await doWhat(timer, currentRecord.Tally); // 只要执行成功一次,那么清空异常信息 currentRecord.Timer.Exception.Clear(); // 执行成功通知 if (timer.Type == SpareTimeTypes.Interval && !onlyInspect) { await WriteChannel(timer, 2); } } catch (Exception ex) { // 执行异常通知 if (timer.Type == SpareTimeTypes.Interval && !onlyInspect) { await WriteChannel(timer, 3); } // 记录任务异常 currentRecord.Timer.Exception.TryAdd(currentRecord.Tally, ex); // 如果任务执行超过 10 次失败,则停止任务 if (currentRecord.Timer.Exception.Count > 10) { Stop(workerName, true); } } finally { // 释放未托管对象 App.DisposeUnmanagedObjects(); // 处理串行执行问题 currentRecord.IsCompleteOfPrev = true; // 更新任务记录 UpdateWorkerRecord(workerName, currentRecord); } // 如果间隔小于或等于 0 取消任务 if (interval <= 0) { Cancel(workerName); } // 停止任务 if (!continued) { Cancel(workerName); } // 处理重入问题 Interlocked.Exchange(ref interlocked, 0); } } // 订阅执行事件 timer.Elapsed += (sender, e) => handler(sender, e).GetAwaiter().GetResult(); timer.AutoReset = continued; if (startNow) { Start(timer.WorkerName); } }
/// <summary> /// 开始执行简单任务(持续的) /// </summary> /// <param name="interval">时间间隔(毫秒)</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="executeType"></param> public static void Do(double interval, Action <SpareTimer, long> 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); }
/// <summary> /// 开始执行下一发生时间任务 /// </summary> /// <param name="nextTimeHandler">返回下一次执行时间</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime">在下一个空时间取消任务</param> /// <param name="executeType"></param> public static void Do(Func <DateTimeOffset?> nextTimeHandler, Func <SpareTimer, long, Task> doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel) { if (doWhat == null) { return; } // 每 1s 秒检查一次 Do(1000, async(timer, tally) => { // 获取下一个执行的时间 var nextLocalTime = nextTimeHandler(); // 判断是否在下一个空时间取消任务 if (cancelInNoneNextTime) { if (nextLocalTime == null) { Cancel(timer.WorkerName); return; } } else { if (nextLocalTime == null) { return; } } // 获取当前任务的记录 _ = WorkerRecords.TryGetValue(timer.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()).TotalSeconds; if (Math.Floor(interval) != 0) { UpdateWorkerRecord(timer.WorkerName, currentRecord); return; } // 延迟 100ms 后执行,解决零点问题 await Task.Delay(100); // 更新实际执行次数 currentRecord.Timer.Tally = timer.Tally = currentRecord.CronActualTally += 1; UpdateWorkerRecord(timer.WorkerName, currentRecord); // 执行前通知 await WriteChannel(timer, 1); // 执行方法 await doWhat(timer, currentRecord.CronActualTally); // 执行后通知 await WriteChannel(timer, 2); }, workerName, description, startNow, cancelInNoneNextTime, executeType, true); }
/// <summary> /// 开始执行简单任务 /// </summary> /// <param name="intervalHandler">时间间隔(毫秒)</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="executeType"></param> /// <param name="continued">是否持续执行</param> public static void Do(Func <double> intervalHandler, Action <SpareTimer, long> 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); }
/// <summary> /// 开始执行下一发生时间任务 /// </summary> /// <param name="nextTimeHandler">返回下一次执行时间</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime">在下一个空时间取消任务</param> /// <param name="executeType"></param> public static void Do(Func <DateTimeOffset?> nextTimeHandler, Action <SpareTimer, long> 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); }
/// <summary> /// 开始执行 Cron 表达式任务 /// </summary> /// <param name="expression">Cron 表达式</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="cronFormat">配置 Cron 表达式格式化</param> /// <param name="executeType"></param> public static void Do(string expression, Func <SpareTimer, long, Task> 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); }
/// <summary> /// 开始执行简单任务 /// </summary> /// <param name="intervalHandler">时间间隔(毫秒)</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="executeType"></param> /// <param name="continued">是否持续执行</param> public static void Do(Func <double> intervalHandler, Action <SpareTimer, long> doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel, bool continued = true) { 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 }; // 订阅执行事件 timer.Elapsed += async(sender, e) => { // 获取当前任务的记录 _ = WorkerRecords.TryGetValue(workerName, out var currentRecord); // 处理串行执行问题 if (timer.ExecuteType == SpareTimeExecuteTypes.Serial) { if (!currentRecord.IsCompleteOfPrev) { return; } // 立即更新多线程状态 currentRecord.IsCompleteOfPrev = false; UpdateWorkerRecord(workerName, currentRecord); } // 记录执行次数 currentRecord.Timer.Tally = currentRecord.Tally += 1; // 处理多线程并发问题(重入问题) var interlocked = currentRecord.Interlocked; if (Interlocked.Exchange(ref interlocked, 1) == 0) { try { // 执行任务 doWhat(timer, currentRecord.Tally); } catch (Exception ex) { // 记录任务异常 currentRecord.Timer.Exception.TryAdd(currentRecord.Tally, ex); // 如果任务执行超过 10 次失败,则停止任务 if (currentRecord.Timer.Exception.Count > 10) { Stop(workerName, true); } } finally { // 处理串行执行问题 currentRecord.IsCompleteOfPrev = true; // 更新任务记录 UpdateWorkerRecord(workerName, currentRecord); } // 如果间隔小于或等于 0 取消任务 if (interval <= 0) { Cancel(workerName); } // 停止任务 if (!continued) { Cancel(workerName); } // 处理重入问题 Interlocked.Exchange(ref interlocked, 0); await Task.CompletedTask; } }; timer.AutoReset = continued; if (startNow) { timer.Start(); } }
/// <summary> /// 模拟后台执行任务 /// <para>10毫秒后执行</para> /// </summary> /// <param name="doWhat"></param> /// <param name="interval"></param> /// <param name="cancelInNoneNextTime"></param> /// <param name="executeType"></param> public static void DoIt(Action doWhat = default, double interval = 30, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel) { if (doWhat == null) { return; } DoOnce(interval, async(_, _) => { doWhat(); await Task.CompletedTask; }, cancelInNoneNextTime: cancelInNoneNextTime, executeType: executeType); }
/// <summary> /// 开始执行下一发生时间任务 /// </summary> /// <param name="nextTimeHandler">返回下一次执行时间</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> /// <param name="startNow"></param> /// <param name="cancelInNoneNextTime">在下一个空时间取消任务</param> /// <param name="executeType"></param> public static void Do(Func <DateTime?> nextTimeHandler, Action <SpareTimer, long> doWhat = default, string workerName = default, string description = default, bool startNow = true, bool cancelInNoneNextTime = true, SpareTimeExecuteTypes executeType = SpareTimeExecuteTypes.Parallel) { if (doWhat == null) { return; } // 每秒检查一次 Do(1000, async(timer, tally) => { // 获取下一个执行的时间 var nextLocalTime = nextTimeHandler(); // 判断是否在下一个空时间取消任务 if (cancelInNoneNextTime) { if (nextLocalTime == null) { Cancel(workerName); return; } } else { if (nextLocalTime == null) { return; } } // 只有时间相等才触发 var interval = (nextLocalTime.Value - DateTime.Now).TotalSeconds; if (Math.Floor(interval) != 0) { return; } // 获取当前任务的记录 _ = WorkerRecords.TryGetValue(workerName, out var currentRecord); // 更新任务信息 currentRecord.Timer.Type = timer.Type = SpareTimeTypes.Cron; currentRecord.Timer.Status = timer.Status = SpareTimeStatus.Running; currentRecord.CronActualTally += 1; UpdateWorkerRecord(workerName, currentRecord); // 执行方法 doWhat(timer, currentRecord.CronActualTally); await Task.CompletedTask; }, workerName, description, startNow, cancelInNoneNextTime, executeType); }