예제 #1
0
 /// <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);
 }
예제 #2
0
        /// <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);
        }
예제 #3
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);
            }
        }
예제 #4
0
 /// <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);
 }
예제 #5
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);
        }
예제 #6
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)
 {
     Do(intervalHandler, async(s, i) =>
     {
         doWhat(s, i);
         await Task.CompletedTask;
     }, workerName, description, startNow, cancelInNoneNextTime, executeType, continued);
 }
예제 #7
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, 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);
 }
예제 #8
0
 /// <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);
 }
예제 #9
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();
            }
        }
예제 #10
0
        /// <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);
        }
예제 #11
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;
                    }
                }

                // 只有时间相等才触发
                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);
        }