AdolphYang

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一  定时任务基础:

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

 

posted on 2015-11-07 07:55  AdolphYang  阅读(2056)  评论(0编辑  收藏  举报