Example #1
0
        /// <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();
            }
        }
Example #2
0
        /// <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();
            }
        }
Example #3
0
        /// <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));
        }
Example #4
0
        /// <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));
        }
Example #5
0
        /// <summary>
        /// 获取单个任务信息
        /// </summary>
        /// <param name="workerName"></param>
        /// <returns></returns>
        public static SpareTimer GetWorker(string workerName)
        {
            if (string.IsNullOrWhiteSpace(workerName))
            {
                throw new ArgumentNullException(nameof(workerName));
            }

            return(WorkerRecords.FirstOrDefault(u => u.Value.Timer.WorkerName == workerName).Value?.Timer);
        }
Example #6
0
        /// <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);
        }
Example #7
0
        /// <summary>
        /// 销毁所有任务
        /// </summary>
        public static void Dispose()
        {
            if (!WorkerRecords.Any())
            {
                return;
            }

            foreach (var workerRecord in WorkerRecords)
            {
                Cancel(workerRecord.Key);
            }
        }
Example #8
0
        /// <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);
        }
Example #9
0
        /// <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();
        }
Example #10
0
        /// <summary>
        /// 取消某个任务
        /// </summary>
        /// <param name="workerName"></param>
        public static void Cancel(string workerName)
        {
            if (string.IsNullOrWhiteSpace(workerName))
            {
                throw new ArgumentNullException(nameof(workerName));
            }

            // 判断任务是否存在
            if (!WorkerRecords.TryRemove(workerName, out var workerRecord))
            {
                return;
            }

            // 获取定时器
            var timer = workerRecord.Timer;

            // 停止并销毁任务
            timer.Status = SpareTimeStatus.CanceledOrNone;
            timer.Stop();
            timer.Dispose();
        }
Example #11
0
 /// <summary>
 /// 获取所有任务列表
 /// </summary>
 /// <returns></returns>
 public static IEnumerable <SpareTimer> GetWorkers()
 {
     return(WorkerRecords.Select(u => u.Value.Timer));
 }
Example #12
0
        /// <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);
            }
        }
Example #13
0
        /// <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);
        }
Example #14
0
 /// <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);
 }
Example #15
0
 /// <summary>
 /// 获取所有任务列表
 /// </summary>
 /// <returns></returns>
 public static IEnumerable <SpareTimer> GetTasks()
 {
     return(WorkerRecords.Where(u => !u.Key.StartsWith(">>> "))
            .Select(u => u.Value.Timer));
 }
Example #16
0
        /// <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();
            }
        }