• Quartz 定时任务(含Redis)


    一  定时任务基础:

    MQ:Message Queue
    消息队列服务器:MSMQ、ActiveMQ、Redis等
    项目任务:确定邮件的发送,重置密码的发送(发送可能会很慢,而且有可能还需要重试),用消息队列把注册过程和邮件发送过程分开

    二  示例:

      //testMessageQueue.csProj

    namespace testMessageQueue
    {
        class Program
        {
            static void Main(string[] args)
            {
                /*
                while(true)
                {
                    string email=Console.ReadLine();
                    using(IRedisClient client=RedisManager.ClientManager.GetClient())
                    {
                        client.EnqueueItemOnList("TestEmail", email);
                    }
                }
                 */
    
                using(IRedisClient client=RedisManager.ClientManager.GetClient())
                {
                    while(true)
                    {
                        string email = client.DequeueItemFromList("TestEmail");
                        if(email==null)
                        {
                            Console.WriteLine("等待输入");
                            Thread.Sleep(100);
                            continue;
                        }
                        Console.WriteLine("发送邮箱:eamil=" + email);
                    }
                }
    
                Console.ReadKey();
            }
        }
    
    
        public class RedisManager
        {
            public static PooledRedisClientManager ClientManager { get; private set; } //内部可写,外部只能读
            static RedisManager()
            {
                RedisClientManagerConfig redisConfig = new RedisClientManagerConfig();
                redisConfig.MaxWritePoolSize = 128;
                redisConfig.MaxReadPoolSize = 128;
                ClientManager = new PooledRedisClientManager(new string[] { "127.0.0.1" }, new string[] { "127.0.0.1" }, redisConfig); //在哪几个ip上进行集群的读写分离操作
    
            }
        }
    }
    testMessageQueue.csProj

    三  定时任务框架:

       //testQuartz.csProj

    namespace testQuartz
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            /// <summary>
            /// 定时任务
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnQuartz_Click(object sender, EventArgs e)
            {
                //每隔一段时间执行一个任务
                ISchedulerFactory sf = new StdSchedulerFactory();
                IScheduler sched = sf.GetScheduler(); //获得一个计划任务
                JobDetail job = new JobDetail("job1", "group1", typeof(MyJog)); ////MyJog为实现了IJob接口的类
                DateTime dt = TriggerUtils.GetNextGivenSecondDate(null, 2); //5秒后开始第一次运行
                TimeSpan interval = TimeSpan.FromSeconds(5); //时间段--每隔5s执行一次
                //每若干小时运行一次,小时间隔由appsettings中的IndexIntervalHour参数指定
                Trigger trigger = new SimpleTrigger("trigger1", "group1", "job1", "group1", dt, null, SimpleTrigger.RepeatIndefinitely, interval);
                sched.AddJob(job, true);
                sched.ScheduleJob(trigger);
                sched.Start();
            }
    
        }
        class MyJog : IJob
        {
            public void Execute(JobExecutionContext context)
            {
                MessageBox.Show("我执行了l");
            }
        }
    }

    四  实例:

    (1)原理:

    Quartz.Net实现:每10分钟定时发送系统数据:新增用户数据
    每次用户注册的时候,都把用户的注册信息:用户名、邮箱、手机号等.除了正常的注册之外,额外再把这些数据放入消息队列。
    每隔5分钟,定时从消息队列中取出新注册用户信息,然后发送邮件给业务人员.
    SendNewRegUserEmailJob.cs
    1 直接Global不行: RupengTimer类库 //如鹏定时任务类库(因为在Global中进行会有兼容性问题)
    2 Console控制台程序也不可以: Application.Run(new FormMain()); //加载WinForm时直接启动WinForm程序,因为上面是在WinForm中测试成功的
    3 WinForm中执行定时任务还是不行: 因为时间(与世界标准时间是差8h) ---革零为致时间与北京(东八区)时间差8h
    DateTime.Now 应该是: DateTime dt = TriggerUtils.GetNextGivenSecondDate(null, 1);

    (2)逻辑:

    每10分钟定时发送系统数据:新增用户数据

    1 当用户邮箱被激活,更新激活状态后,获得用户数据
    2 拼接用户数据的字符串 (用户名、邮箱、手机号)
    3 把这个字符串 入队列集合 (Redis_Front_QueueList_AddUser)

    4 执行定时任务框架 (单独RupengTimer类库与进程中,Global中有兼容性问题)
    5 执行出队列任务,获得字符串
    6 如果字符串不为null或长度大于0,发送邮件

    (3)步骤:

      //入队列 (把新增用户信息入队列)

            /// <summary>
            /// 入队列:用于存储新增用户,出队列时发送给指定邮箱
            /// </summary>
            /// <param name="context"></param>
            /// <param name="username">用户名</param>
            public static void RedisEnqueueForUserRegister(HttpContext context, string username)
            {
                #region 逻辑
                //1    当用户邮箱被激活,更新激活状态后,获得用户数据
                //2    拼接用户数据的字符串 (用户名、邮箱、手机号)
                //3    把这个字符串 入队列集合 (Redis_Front_QueueList_AddUser) 
                #endregion
                #region 获得用户数据
                object obj = new MyORM_BLL().SelectModelByUserName(typeof(TD_USER), 1, "T", username);
                if (obj == null)
                {
                    RazorHelper.RazorParse(context, "~/error.cshtml", new { Msg = "数据库错误,未找到该激活用户 username=" + username });
                    context.Response.End();
                }
                TD_USER user = obj as TD_USER; 
                #endregion
                StringBuilder sb = new StringBuilder();
                #region 拼接用户数据的字符串
                sb.Append("用户名:" + user.USERNAME + "|");
                sb.Append("姓名:" + user.REALNAME + "|");
                sb.Append("手机:" + user.MOBILE + "|");
                sb.AppendLine("邮箱:" + user.EMAIL + "|"); 
                #endregion
                using(IRedisClient client=RedisManager.ClientManager.GetClient())
                {
                    client.EnqueueItemOnList(ConstStringHelper.REDIS_FRONT_QUEUELIST_ADDUSER, sb.ToString());
                }
            }
    LoginHelper.RedisEnqueueForUserRegister()

      //窗体加载,就执行定时任务

    namespace DIDAO.TimerForm
    {
        public partial class FormMain : Form
        {
            public FormMain()
            {
                InitializeComponent();
            }
    
            /// <summary>
            /// 窗体一加载,就执行定时任务
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void FormMain_Load(object sender, EventArgs e)
            {
                Timer.TimeSchedule.TimeExecuteSchedule(typeof(SendEmailForAddUser), "triggerAddUser", "groupAddUser", "jobAddUser");
    
            }
        }
    TimerForm.FormMain.Load()

      //定时任务

    namespace DIDAO.Timer
    {
        /// <summary>
        /// 定时任务
        /// </summary>
        public class TimeSchedule
        {
            /// <summary>
            /// 执行定时任务(用于类型type中的任务)
            /// </summary>
            public static void TimeExecuteSchedule(Type type, string triggerName, string groupName, string jobName)
            {
                //每隔一段时间执行一个任务
                ISchedulerFactory sf = new StdSchedulerFactory();
                IScheduler sched = sf.GetScheduler(); //获得一个计划任务
                JobDetail job = new JobDetail(jobName, groupName, type); ////MyJog为实现了IJob接口的类
                //DateTime dt = TriggerUtils.GetNextGivenSecondDate(null, 5); //5秒后开始第一次运行
                //DateTime dt = DateTime.Now; //立即执行
                DateTime dt = TriggerUtils.GetNextGivenSecondDate(null, 1); //1s后开始执行
                TimeSpan interval = TimeSpan.FromMinutes(1); //时间段--每隔60s执行一次
                //每若干小时运行一次,小时间隔由appsettings中的IndexIntervalHour参数指定
                Trigger trigger = new SimpleTrigger(triggerName, groupName, jobName, groupName, dt, null, SimpleTrigger.RepeatIndefinitely, interval);
                sched.AddJob(job, true);
                sched.ScheduleJob(trigger);
                sched.Start();
            }
        }
    Timer.TimeSchedule.cs

    //出队列 发送邮件(新注册用户信息)

    namespace DIDAO.Timer
    {
        public class SendEmailForAddUser:IJob
        {
            /// <summary>
            /// 接收方邮件地址(发送 新用户注册信息时)
            /// </summary>
            private string receiveEmailAddress = ConfigurationManager.AppSettings["receiveEmailAddress"]; //发送方邮箱地址
    
            /// <summary>
            /// 出队列 发送新注册用户信息
            /// </summary>
            /// <param name="context"></param>
            public void Execute(JobExecutionContext context)
            {
                #region 逻辑
                //4    执行定时任务框架 (单独RupengTimer类库与进程中,Global中有兼容性问题)
                //5    执行出队列任务,获得字符串
                //6    如果字符串不为null或长度大于0,发送邮件  
                #endregion
                using(IRedisClient client=RedisManager.ClientManager.GetClient())
                {
                    StringBuilder sb = new StringBuilder();
                    while(true)
                    {
                        string item = client.DequeueItemFromList(ConstStringHelper.REDIS_FRONT_QUEUELIST_ADDUSER);
                        if (item == null)
                        {
                            if(sb==null || sb.Length<=0)
                            {
                                return; //执行下一次定时任务
                            }
                            //发送邮件
                            SendEmailHelper.SendMail(receiveEmailAddress, "DIDAO邮件:新用户注册信息", sb.ToString());
                            sb.Clear();
                        }
                        else
                        {
                            sb.AppendLine(item);
                        }
                    }
                }
    
            }
        }
    }
    Timer.SendEmailForAddUser:IJob
  • 相关阅读:
    心得体悟帖---200130(专业长才(敲门砖))(希望)
    心得体悟帖---200130(一举多的)(少了发自内心的从容)
    范仁义css3课程---19、流动布局
    范仁义css3课程---18、overflow
    日常英语---200130(inspire)
    日常英语---200130(Basketball fans around the world are mourning the death of American superstar Kobe Bryant.)
    视频中的ts文件是什么
    如何美化windows桌面
    心得体悟帖---200127(囚笼-它会推着我的,不必多想)(过好当下,享受当下)
    心得体悟帖---有哪些越早知道越好的人生经验?(转自知乎)
  • 原文地址:https://www.cnblogs.com/adolphyang/p/4944273.html
Copyright © 2020-2023  润新知