Winform开发框架之通用定时服务管理
做项目的时候,或多或少需要和其他外部系统或者接口进行数据交互,有些是单向的获取,有些可能是修改状态后再写回去,不管如何,这个都可以称之为数据同步操作,如人员信息同步、业务数据同步、第三方接口数据同步等等。
数据同步涉及到一个同步时间的问题,一般不敏感的数据,一天或者一周左右同步一次就可以了,有些可能需要间隔更短一点。
同步的逻辑不同,有些可能写数据库就可以了,有些可能需要访问WebService或者其他接口,然后在进行数据获取,保存等操作,回写的时候,也一般是调用WebService这样的接口修改数据。
每个同步实现我们都需要做大量重复性工作,如Windows服务安装、卸载、或者基础性的工作,有没有一种方式可以隔离业务逻辑和常用的东西呢?
1、通用定时服务管理模块设计
这样的同步操作看似没有很多必然的关联性,但是,这些都是很常见的东西,如果以插件架构方式来组织各个不同的业务封装,通过参数配置实现同步间隔不同,核心的同步模块其实是很多类似的东西,而同步一般通过Windows访问进行,这样通用的我们可以把它封装成一个通用的Windows服务。再辅以一个界面管理模块来管理服务的安装、卸载、启动、停止、测试等操作就可以了,整个Window服务的插件设计框架如下所示。
Windows定时服务-文件视图如下所示:
以上架构,有几个特点,
1、 基于插件结构,扩展容易。
2、 一个定时服务【通用的WIndows服务模块】,可以同时运行很多个不同的定时规则的定时服务应用。
3、 一个通用的服务管理界面【Windows定时服务管理】,来对定时服务的安装、卸载、启动、停止、测试等操作,并且可以对插件进行可视化配置。
4、【通用的WIndows服务模块】提供参数化安装,卸载、测试的功能。
5、【Windows定时服务管理】提供DOS测试和WInform进度测试的集成。
6、 插件参数化配置,提供插件各种参数的配置,统一调度。
6、插件通过反射加载不同的定时服务应用,实现松耦合和强类型接口的转换,确保弹性化和安全性。
7、整个定时服务管理模块,可以在不同的场合下实现重用,每次只是定时服务应用的不同而已。
8、定时时间设置,提供多样化的设置,可以在间隔时间、每天整点运行、每月指定日期时间运行多种方式。
整个定时服务管理通用模块,可以最大化的实现工具重用、逻辑重用,不管业务场景如何变化,基本上不需要调整了,只需要把定时服务应用ABC模块开发好,参数配置好,丢进去就可以了。
2、定时服务控制台【Windows定时服务管理】的界面设计
开发好的【Windows定时服务管理】界面如下所示,运行后,会把XML文档里面的插件加载在下面的列表中,供查看和修改操作。
插件的XML配置信息如下所示。
<?xml version="1.0"?> <ArrayOfPlugInSetting> <PlugInSetting> <!--插件程序名称--> <Name>测试名称</Name> <!--插件描述内容--> <Description>测试描述</Description> <!--运行同步服务的间隔时间(单位:分钟)--> <ServiceCycleMinutes>1</ServiceCycleMinutes> <!--Windows服务在固定时刻(0~23时刻)运行--> <ServiceRunAtHour>23</ServiceRunAtHour> <!--Windows服务在每月指定天运行,小时按ServiceRunAtHour的值--> <ServiceRunAtDay>1</ServiceRunAtDay> <!--运行模式,0为间隔分钟运行 1为固定时刻运行, 2为按月某天和小时 其他值为禁用--> <RunMode>0</RunMode> <!--插件的类型名称:插件类名,程序集名称--> <PlugInTypeName>WHC.PlugInService.ClassName,WHC.PlugInService</PlugInTypeName> </PlugInSetting> </ArrayOfPlugInSetting>
单击安装服务,控制台程序调用DOS命令+参数来实现通用定时WIndows服务的安装。
安装后,系统的Windows服务列表中就会增加一个【定时服务】的服务模块了,这样就证明我们顺利安装了通用定时服务了。
定时服务控制台的状态也会同时刷新,并且把服务的状态和类型显示在【服务状态】里面,这个时候,可以对服务进行卸载、测试、停止服务、重新启动、刷新状态等相关操作了。
如果对于很多定时服务应用,每种需要进行动态的禁用或者设置定时方式,那么可以在列表上右键进行相关的操作。
3、定时应用测试及界面集成
在开发过程中,发现经常性的需要调试我们自己的定时应用ABC是否正确生成,可以通过【DOS测试】和【进度测试】这两个按钮进行逻辑测试,这个没有触发Windows的情况下进行调用,可以看到具体的效果如下所示。
一般来说,提供以上DOS窗口来进行跟踪调试就可以了,但是有时候,我们想在Winform程序中调用立即同步的操作的时候,可以使用进度测试的逻辑代码进行处理,这样可以在主界面中显示进度。
由于是插件架构,因此在和Winform集成的时候,其实是和这个定时服务控制台一样,我们在我们的Winform程序中,加载应用插件,进行调用就可以了,调用代码如下所示。
private void btnTestProgress_Click(object sender, EventArgs e) { try { this.lblTips.Visible = true; this.progressBar1.Visible = true; //Winform进度条指示测试 foreach (string key in pluginList.Keys) { ITimingPlugIn obj = pluginList[key]; if (obj != null) { obj.ProgressChanged += new ProgressChangedEventHandler(TimingPlugIn_ProgressChanged); obj.Excute(); LogTextHelper.Info(string.Format("插件【{0}】运行一次", key)); } } MessageUtil.ShowTips("操作完成"); } finally { lblTips.Text = ""; this.lblTips.Visible = false; this.progressBar1.Visible = false; } } void TimingPlugIn_ProgressChanged(object sender, ProgressChangedEventArgs e) { //ITimingPlugIn obj = sender as ITimingPlugIn; progressBar1.Value = e.ProgressPercentage; if (e.UserState != null) { lblTips.Text = e.UserState.ToString(); } Thread.Sleep(100); Application.DoEvents(); }
调用进度测试的界面如下所示,它可以把各种同步详细情况显示在主界面上。
对于整个模块的运行操作,我们通过日志进行记录,这样可以详细看到具体的操作了。