using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace Core.Util
{
    /// <summary>
    ///Task help class
    /// </summary>
    public static class JobHelper
    {
        #regionPrivate members

        private static IScheduler __scheduler;
        private static object _lock = new object(a);private static IScheduler _scheduler
        {
            get
            {
                if (__scheduler == null)
                {
                    lock (_lock)
                    {
                        if (__scheduler == null) { __scheduler = AsyncHelper.RunSync(() => StdSchedulerFactory.GetDefaultScheduler()); AsyncHelper.RunSync(() => __scheduler.Start()); }}}return__scheduler; }}static ConcurrentDictionary<string, Action> _jobs { get; }
            = new ConcurrentDictionary<string, Action>();

        #endregion

        #regionExternal interface

        /// <summary>
        ///Sets a loop operation at a time interval
        /// </summary>
        /// <param name="action">Operations performed</param>
        /// <param name="timeSpan">The time interval</param>
        /// <returns>Task Id</returns>
        public static string SetIntervalJob(Action action, TimeSpan timeSpan)
        {
            string key = Guid.NewGuid().ToString();
            _jobs[key] = action;
            IJobDetail job = JobBuilder.Create<Job>()
               .WithIdentity(key)
               .Build();
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(key)
                .StartNow()
                .WithSimpleSchedule(x => x.WithInterval(timeSpan).RepeatForever())
                .Build();
            AsyncHelper.RunSync(() => _scheduler.ScheduleJob(job, trigger));

            return key;
        }

        /// <summary>
        ///Set a scheduled task for each day
        /// </summary>
        /// <param name="action">Tasks performed</param>
        /// <param name="h">when</param>
        /// <param name="m">points</param>
        /// <param name="s">seconds</param>
        /// <returns>Task Id</returns>
        public static string SetDailyJob(Action action, int h, int m, int s)
        {
            string key = Guid.NewGuid().ToString();
            _jobs[key] = action;
            IJobDetail job = JobBuilder.Create<Job>()
               .WithIdentity(key)
               .Build();
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(key)
                .StartNow()
                .WithCronSchedule($"{s} {m} {h}* *?")// Time every day
                .Build();
            AsyncHelper.RunSync(() => _scheduler.ScheduleJob(job, trigger));

            return key;
        }

        /// <summary>
        ///To set a delay task, perform it only once
        /// </summary>
        /// <param name="action">Operations performed</param>
        /// <param name="delay">Delay time</param>
        /// <returns>Task Id</returns>
        public static string SetDelayJob(Action action, TimeSpan delay)
        {
            string key = Guid.NewGuid().ToString();
            action += () =>
            {
                RemoveJob(key);
            };
            _jobs[key] = action;

            IJobDetail job = JobBuilder.Create<Job>()
               .WithIdentity(key)
               .Build();
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(key)
                .StartAt(DateTime.Now + delay)
                .WithSimpleSchedule(x => x.WithRepeatCount(0).WithInterval(TimeSpan.FromSeconds(10)))
                .Build();
            AsyncHelper.RunSync(() => _scheduler.ScheduleJob(job, trigger));

            return key;
        }

        /// <summary>
        ///Create tasks through expressions
        ///Expression rules refer to: http://www.jsons.cn/quartzcron/
        /// </summary>
        /// <param name="action">Operations performed</param>
        /// <param name="cronExpression">expression</param>
        /// <returns></returns>
        public static string SetCronJob(Action action, string cronExpression)
        {
            string key = Guid.NewGuid().ToString();
            _jobs[key] = action;
            IJobDetail job = JobBuilder.Create<Job>()
               .WithIdentity(key)
               .Build();
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(key)
                .StartNow()
                .WithCronSchedule(cronExpression)
                .Build();
            AsyncHelper.RunSync(() => _scheduler.ScheduleJob(job, trigger));

            return key;
        }

        /// <summary>
        ///Delete the task
        /// </summary>
        /// <param name="jobId">Task Id</param>
        public static void RemoveJob(string jobId)
        {
            AsyncHelper.RunSync(() => _scheduler.DeleteJob(new JobKey(jobId)));
            _jobs.TryRemove(jobId, out _);
        }

        #endregion

        #regionThe inner class

        private class Job : IJob
        {
            public async Task Execute(IJobExecutionContext context)
            {
                await Task.Run(() =>
                {
                    string jobName = context.JobDetail.Key.Name;
                    if(_jobs.ContainsKey(jobName)) { _jobs[jobName]? .Invoke(); }}); }}#endregion}}Copy the code