/// <summary> /// 开始某个任务 /// </summary> /// <param name="workerName"></param> public static void Start(string workerName) { if (string.IsNullOrWhiteSpace(workerName)) { throw new ArgumentNullException(workerName); } // 判断任务是否存在 if (!WorkerRecords.TryGetValue(workerName, out var workerRecord)) { return; } // 获取定时器 var timer = workerRecord.Timer; // 启动任务 if (!timer.Enabled) { // 任务开始通知 WriteChannel(timer, 0).GetAwaiter().GetResult(); // 如果任务过去是失败的,则清除异常信息后启动 if (timer.Status == SpareTimeStatus.Failed) { timer.Exception.Clear(); } timer.Status = SpareTimeStatus.Running; timer.Start(); } }
/// <summary> /// 停止某个任务 /// </summary> /// <param name="workerName"></param> /// <param name="isFaild"></param> public static void Stop(string workerName, bool isFaild = false) { if (string.IsNullOrWhiteSpace(workerName)) { throw new ArgumentNullException(nameof(workerName)); } // 判断任务是否存在 if (!WorkerRecords.TryGetValue(workerName, out var workerRecord)) { return; } // 获取定时器 var timer = workerRecord.Timer; // 停止任务 if (timer.Enabled) { // 任务停止通知 WriteChannel(timer, -1).GetAwaiter().GetResult(); timer.Status = !isFaild ? SpareTimeStatus.Stopped : SpareTimeStatus.Failed; timer.Stop(); } }
/// <summary> /// 停止某个任务 /// </summary> /// <param name="workerName"></param> public static void Stop(string workerName) { if (string.IsNullOrWhiteSpace(workerName)) { throw new ArgumentNullException(nameof(workerName)); } // 判断任务是否存在 if (!WorkerRecords.TryGetValue(workerName, out var workerRecord)) { return; } // 获取定时器 var timer = workerRecord.Timer; // 停止任务 if (timer.Enabled) { timer.Status = SpareTimeStatus.Stopped; timer.Stop(); } // 暂停子任务 Stop(GetSubWorkerName(workerName)); }
/// <summary> /// 开始某个任务 /// </summary> /// <param name="workerName"></param> public static void Start(string workerName) { if (string.IsNullOrWhiteSpace(workerName)) { throw new ArgumentNullException(workerName); } // 判断任务是否存在 if (!WorkerRecords.TryGetValue(workerName, out var workerRecord)) { return; } // 获取定时器 var timer = workerRecord.Timer; // 启动任务 if (!timer.Enabled) { timer.Status = SpareTimeStatus.Running; timer.Start(); } // 开启子任务 Start(GetSubWorkerName(workerName)); }
/// <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; } } // 获取当前任务的记录 _ = 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 - DateTime.Now).TotalSeconds; if (Math.Floor(interval) != 0) { UpdateWorkerRecord(workerName, currentRecord); return; } // 更新实际执行次数 currentRecord.Timer.Tally = timer.Tally = currentRecord.CronActualTally += 1; UpdateWorkerRecord(workerName, currentRecord); // 执行方法 doWhat(timer, currentRecord.CronActualTally); await Task.CompletedTask; }, workerName, description, startNow, cancelInNoneNextTime, executeType); }
/// <summary> /// 开始执行下一发生时间任务 /// </summary> /// <param name="nextTimeHandler">返回下一次执行时间</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> public static void Do(Func <DateTime?> nextTimeHandler, Action <SpareTimer, long> doWhat = default, string workerName = default, string description = default) { if (doWhat == null) { return; } workerName ??= Guid.NewGuid().ToString("N"); // 每秒检查一次 Do(1000, (timer, tally) => { // 获取下一个执行的时间 var nextLocalTime = nextTimeHandler(); if (nextLocalTime == null) { Cancel(workerName); } // 获取当前任务的记录 _ = WorkerRecords.TryGetValue(workerName, out var currentRecord); // 处理重复创建定时器问题 if (currentRecord.CronNextOccurrenceTime != null) { return; } currentRecord.CronNextOccurrenceTime = nextLocalTime.Value; UpdateWorkerRecord(workerName, currentRecord); // 设置执行类型 timer.Type = SpareTimeTypes.Cron; timer.Status = SpareTimeStatus.Running; // 执行任务 var interval = (nextLocalTime.Value - DateTime.Now).TotalMilliseconds; DoOnce(interval, (subTimer, subTally) => { // 清空下一个记录时间,并写入实际执行计数 _ = WorkerRecords.TryGetValue(workerName, out var currentRecord); currentRecord.CronActualTally += 1; currentRecord.CronNextOccurrenceTime = null; UpdateWorkerRecord(workerName, currentRecord); // 执行方法 doWhat(timer, currentRecord.CronActualTally); }, GetSubWorkerName(workerName), description); }, workerName, description); }
/// <summary> /// 开始执行简单任务 /// </summary> /// <param name="interval">时间间隔(毫秒)</param> /// <param name="continued">是否持续执行</param> /// <param name="doWhat"></param> /// <param name="workerName"></param> /// <param name="description"></param> public static void Do(double interval, bool continued = true, Action <SpareTimer, long> doWhat = default, string workerName = default, string description = default) { if (string.IsNullOrWhiteSpace(workerName) || doWhat == null) { return; } // 创建定时器 var timer = new SpareTimer(interval, workerName) { Type = SpareTimeTypes.Interval, Description = description, Status = SpareTimeStatus.Running }; // 订阅执行事件 timer.Elapsed += (sender, e) => { // 获取当前任务的记录 _ = WorkerRecords.TryGetValue(workerName, out var currentRecord); // 停止任务 if (!continued) { Cancel(timer.WorkerName); } // 记录执行次数 currentRecord.Tally += 1; // 处理多线程并发问题(重入问题) var interlocked = currentRecord.Interlocked; if (Interlocked.Exchange(ref interlocked, 1) == 0) { // 更新任务记录 UpdateWorkerRecord(workerName, currentRecord); // 执行任务 doWhat(timer, currentRecord.Tally); // 处理重入问题 Interlocked.Exchange(ref interlocked, 0); } }; timer.AutoReset = continued; timer.Start(); }
/// <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="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="workerName"></param> /// <param name="newRecord"></param> private static void UpdateWorkerRecord(string workerName, WorkerRecord newRecord) { _ = WorkerRecords.TryGetValue(workerName, out var currentRecord); _ = WorkerRecords.TryUpdate(workerName, newRecord, currentRecord); }
/// <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(); } }