任务集框架的设计
任务集框架的设计意图
该框架设计主要用于后台执行任务,只需要动态的去添加执行任务即可,而不需要关心任务开始、停止以及任务状态信息等。旨在更加方便的去管理多个任务。
任务集框架的设计图
任务集框架设置图如下,主要分为4大模块,config、log、help、task 这四个模块。
Config 模块主要是各个任务的配置文件。
Log模块主要是记录各个任务产生的日志文件。
Helper模块主要是所有的任务需要用到的工具集。
Tasks 模块主要是各个任务的集合
任务集框架的设计模块详解
1. 主程序模块
该模块主要用于任务框架开启停止的入口,同时配置界面,可以在框架运行过程中手动
开启,停止任务以及配置任务。通过界面展示,可以详细的看到任务的执行次数,错误次数以及任务的当前状态。界面如下:
任务状态:表示任务当前的执行状态。表示当前任务未开启,表示当前任务已暂停,表示当前任务正在运行中。
任务次数:表示当前任务总共执行的次数。
错误次数:表示当前任务总共执行的错误次数
任务周期:表示当前任务执行了多少个任务周期,一个周期是86400个任务次数。
2. Config模块
该模块用于所有的任务的配置。
示例如下:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<dataenginerpath>C:\Users\lining\Documents\Visual Studio 2015\Projects1\EcgNetPlug\bin\x86\Debug\config\FetalDataEnginer\release\testpro.exe</dataenginerpath>
<dataenginername>testPro</dataenginername>
<!--休眠时间-->
<sleeptime>10000</sleeptime>
</root>
3. Log模块
该模块用于记录所有的任务在运行期间的日志数据。该模块使用Log4Net,一个开源的
日志库。感觉还是挺好用的。几乎能想到的功能都有。
日志示例如下:
2017-07-24 08:47:56,382 FetalDataEnginerWorkJob [8] ERROR Process.Kill:拒绝访问。
2017-07-24 08:48:08,891 FetalDataEnginerWorkJob [8] ERROR Process.Kill:拒绝访问。
2017-07-24 08:58:01,891 FetalDataEnginerWorkJob [9] ERROR Process.Kill:拒绝访问。
2017-07-24 08:58:12,431 FetalDataEnginerWorkJob [9] ERROR Process.Kill:拒绝访问。
2017-07-24 09:00:08,782 FetalDataEnginerWorkJob [10] ERROR Process.Kill:拒绝访问。
2017-07-24 09:04:39,821 FetalDataEnginerWorkJob [9] ERROR Process.Kill:拒绝访问。
2017-07-24 10:22:19,719 FetalDataEnginerWorkJob [10] ERROR Process.Kill:拒绝访问。
2017-07-24 10:24:03,266 FetalDataEnginerWorkJob [1] ERROR Process.Kill:拒绝访问。
2017-07-24 10:25:33,186 FetalDataEnginerWorkJob [1] ERROR Process.Kill:拒绝访问。
2017-07-24 10:30:00,554 FetalDataEnginerWorkJob [1] ERROR Process.Kill:拒绝访问。
2017-07-24 10:43:53,695 FetalDataEnginerWorkJob [1] ERROR Process.Kill:拒绝访问。
2017-07-24 14:43:51,249 FetalDataEnginerWorkJob [10] ERROR Process.Kill:拒绝访问。
2017-07-24 16:17:50,396 FetalDataEnginerWorkJob [9] ERROR Process.Kill:拒绝访问。
2017-07-24 16:18:07,162 FetalDataEnginerWorkJob [10] ERROR Process.Kill:拒绝访问。
4. Helper 模块
该模块主要是一些工具的集合,该项目中目前存放一些数据库的操作类,以及XML 文
档的操作类等。
5. Tasks模块
该模块是所有的任务执行实体,每个任务继承BaseJob,然后实现里面的Start Stop 和
Run 方法。BaseJob 会在每秒钟会发送一次任务的执行状态,任务子类发送自己的状态信息给主程序。
示例代码如下:
StatisticWorkJob.cs
public class StatisticWorkJob:BaseJob
{
private ILog log = null;
private string connStr = "";
private StatisticWorkDb db = null;
private int sleepTime = 2000;
public StatisticWorkJob(string name)
{
Init(name);
}
public override void Init(string name)
{
base.Init(name);
log = LogManager.GetLogger("StatisticWorkJob");
}
public override bool Start(int sleep = 1000)
{
log.Info("Start");
bool ret = false;
ret = ReadConfigFile();
if (!ret)
{
log.Error("ReadConfigFile is false and return");
ReportWorkState(2, 1);
return false;
}
db = new StatisticWorkDb(connStr);
return base.Start(sleepTime);
}
public override bool Stop()
{
return base.Stop();
}
public override void Run()
{
while(running)
{
//第一件事 更新所有的区的医疗服务中心数量
DoThingsUpdateAllMedicalServiceNum();
//第二件事 更新所有的科室的设备数量
DoThingUpdateAllMedicalDeviceNum();
//第三件事 更新所有的统计诊端表
DoThingUpdateAllDiagnosNum();
//Thread.Sleep(sleepTime);
base.Run();
}
}
private void DoThingUpdateAllDiagnosNum()
{
try
{
//throw new NotImplementedException();
}
catch(Exception e)
{
log.Error("DoThingUpdateAllDiagnosNum:error:" + e.Message);
ReportWorkState(2, 1);
}
}
private void DoThingUpdateAllMedicalDeviceNum()
{
try
{
}
catch(Exception e)
{
log.Error("DoThingUpdateAllMedicalDeviceNum:error:" + e.Message);
ReportWorkState(2, 1);
}
}
private void DoThingsUpdateAllMedicalServiceNum()
{
try
{
}
catch (Exception e)
{
log.Error("DoThingsUpdateAllMedicalServiceNum:error:" + e.Message);
ReportWorkState(2, 1);
}
}
private bool ReadConfigFile()
{
bool ret = false;
XmlHelperEx xmlHelper = new XmlHelperEx();
try
{
if (xmlHelper.LoadXmlFile(configDirectory + "config.xml"))
{
//加载链接字符串
connStr = xmlHelper.GetValue("root/connectionStrings");
sleepTime = Convert.ToInt32(xmlHelper.GetValue("root/sleeptime"));
ret = true;
}
}
catch
{
log.Error("LoadXmlFile:" + configDirectory + "config.xml");
ReportWorkState(2, 1);
}
return ret;
}
}
BaseJob.cs
public class BaseJob
{
public string jsonName = "";
public Thread td = null;
public bool running = false;
private int sleepTimeState = 1000;
public int sleepTimeWork = 1000;
private int sleepTemp = 0;
public string workName = string.Empty;
public string configDirectory = string.Empty;
public delegate void DelagateWorkState(string name,int code,int cnt);
public event DelagateWorkState evetWorkState = null;
public virtual void Init(string name)
{
workName = name;
configDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
}
public void SetConfigDirectory(string dir)
{
configDirectory = dir;
}
public string GetConfigDirectory()
{
return configDirectory;
}
public virtual bool Start(int sleep = 1000)
{
bool ret = false;
if (!running)
{
sleepTimeWork = sleep;
try
{
running = true;
td = new System.Threading.Thread(Run);
td.Start();
ret = true;
}
catch
{
ret = false;
}
}
return ret;
}
public virtual bool Stop()
{
bool ret = false;
if(running)
{
try
{
if (td != null)
{
running = false;
td.Abort();
ret = true;
}
}
catch
{
ret = false;
}
}
return ret;
}
public string GetWorkName()
{
return workName;
}
private int WaitingWorkTime()
{
int sleeptime = 0;
if(sleepTimeWork < sleepTimeState)
{
sleeptime = sleepTimeWork;
}
else
{
if(sleepTemp + sleepTimeState >= sleepTimeWork)
{
sleeptime = sleepTemp + sleepTimeState - sleepTimeWork;
sleepTemp = 0;
}
else
{
sleeptime = sleepTimeState;
sleepTemp += sleepTimeState;
}
}
return sleeptime;
}
public void ReportWorkState(int code,int cnt)
{
if(evetWorkState != null)
{
evetWorkState(workName,code,cnt);
}
}
public virtual void Run()
{
int sleeptime = WaitingWorkTime();
ReportWorkState(1,1);
Thread.Sleep(sleeptime);
}
}