• [实践]开发扩展性良好的windows服务


    工作中, 我们常常需要开发windows服务, 那么, 一个可维护性好, 可扩展性高的的windows程序可以使我们省去不少的时间和精力.

    我们来分析一下

    一个windows服务应该看成是一个对象, 它拥有以下基本行为

    行为: 执行行为.(这个服务要做什么事)

    同一种行为, 不同的实现逻辑, 典型的工厂模式.

    下面, 我们来定义两个windows服务类

    public class OneTask : IWindowTask
        {
            public void Run(params object[] parms)
            {
                Console.WriteLine("我是第一个window模拟服务.第一第一");
            }
        }
    public class TwoTask:IWindowTask
        {
            public void Run(params object[] parms) {
                Console.WriteLine("我是第二个window模拟服务.第二第二");
            }
        }

    以及约束其行为的接口

    public interface IWindowTask
        {
            void Run(params object[] parms);
        }

    数据表image

    添加两条记录image

    工厂

    public class TaskFactory
        {
            static Hashtable ht = Hashtable.Synchronized(new Hashtable());
     
            public static IWindowTask GetTask(string classPath, IList parms) {
                if (ht[classPath] != null)
                    return (IWindowTask)ht[classPath];
                else {
                    //var taskInstance = Activator.CreateInstance(Type.GetType(classPath));
                    //var taskInstance = System.Reflection.Assembly.Load("MyWindowServiceFramwork").CreateInstance(classPath);
                    object taskInstance=null;
                        taskInstance = Type.GetType(classPath).GetConstructor(Type.EmptyTypes).Invoke(null);
                    ht[classPath] = taskInstance;
                    return (IWindowTask)taskInstance;
                }
            }
            public static IWindowTask GetTask(string classPath) {
                return GetTask(classPath, null);
            }
        }

    枚举

    public enum InterValType { 
            second=1,
            minute=2,
            hour=3,
            day=4,
            week=5,
            month=6
        }

    //给定时控件添加一个任务类ID的属性, 在下面要用到
    class MyTime : System.Timers.Timer {
                public int TaskID { get; set; }
            }
    private static void NewMethod1()
            {
                MyPractiseEntities enty = new MyPractiseEntities();
                //获得所有的有效任务.
                var tasks = enty.MyTask.Where(x => x.enable == true);
                foreach (var item in tasks)
                {
                    MyTime mytime = new MyTime();
                    mytime.TaskID = item.ID;//将任务ID付给当前的定时类ID
                    mytime.Start(); //开始, 默认间隔是100毫秒
     
                    //达到时间间隔执行. 可以理解为每一个定时控件都是一个新的线程. 
                    mytime.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e)
                    {
                        //记录逻辑操作耗时多少, 用以计算下一次运行此方法的时间间隔.
                        System.Diagnostics.Stopwatch stop = new System.Diagnostics.Stopwatch();
                        stop.Start();
     
                        MyPractiseEntities enty2 = new MyPractiseEntities();
                        var currentTimer = sender as MyTime;
                        //必须通过当前的时间控件重新获得数据库对象. 如果直接写item(见上一级的foreach), 那么得到的item始终是tasks集合的最后一个.
                        var currentitem = enty2.MyTask.Where(x => x.ID == currentTimer.TaskID).FirstOrDefault();
                        //如果当前任务满足执行条件
                        if (currentitem.LastRunTime <= DateTime.Now && (currentitem.NextRunTime == null || currentitem.NextRunTime <= DateTime.Now))
                        {
                            currentTimer.Stop();//暂停当前任务
                            //填充当前任务的所有参数
                            var itemParameter = enty2.MyTaskParameter.Where(x => x.TaskID == currentitem.ID).ToList();
                            Func<IList<MyTaskParameter>, object[]> toObjects=x=>{
                                object[] objs =new object[ x.Count];
                                for (int i = 0; i < x.Count; i++)
                                {
                                    objs[i] = x[i].ParmValue;
                                }
                                return objs;
                            };
                            //获得并执行
                            //使用工厂反射出需要执行的任务类,并转化为接口对象/
                            IWindowTask itask = TaskFactory.GetTask(currentitem.ClassPath);
                            //执行
                            itask.Run(toObjects(itemParameter));
     
                            System.Threading.Thread.Sleep(2000);
     
                            //更新下一次执行的时间
                            Func<int, InterValType, double> plusSecond = (intervalue, intervalueType) =>
                            {
                                var temp = 0;
                                switch ((int)intervalueType)
                                {
                                    case 1: temp = currentitem.Interval.Value; break;
                                    case 2: temp = currentitem.Interval.Value * 60; break;
                                    case 3: temp = currentitem.Interval.Value * 60 * 60; break;
                                    case 4: temp = currentitem.Interval.Value * 60 * 60 * 24; break;
                                }
                                return temp;
                            };
                            //读取配置文件来获得时间间隔
                            var tempsecond = plusSecond(currentitem.Interval.Value, (InterValType)currentitem.IntervalType.Value);
     
     
                            DateTime d1 = currentitem.NextRunTime.Value;
                            currentitem.NextRunTime = d1.AddSeconds(tempsecond);
                            currentitem.LastRunTime = DateTime.Now;
                            enty2.SaveChanges();//更新任务的状态信息
     
                            stop.Stop();//监视停止
                            //时间控件下一次执行的时间间隔为配置间隔减去这次运行时长.
                            currentTimer.Interval = tempsecond * 1000 - stop.ElapsedMilliseconds;
                            //开始时间控件
                            currentTimer.Start();
     
                            Console.WriteLine(); Console.WriteLine();
                        }
                    };
                }
            }

    程序下载: 见群共享搜索MyWIndowService

  • 相关阅读:
    练习:使用nmcli 配置网络连接
    编辑网络配置文件
    ETCD安装
    LInux部署本地DNSbind9
    Linux 修改tomcat9相关参数优化
    Linux-编写SHELL 加密解密方法
    Jenkins的安装部署
    lepus 配置监控Mysql+Redis+Mongodb服务器
    lepus部署
    prometheus + grafana 安装 监控 redis mysql mongodb Linux服务器
  • 原文地址:https://www.cnblogs.com/jianjialin/p/2098551.html
Copyright © 2020-2023  润新知