123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- using System;
- using System.Reflection;
- using System.Configuration;
- using Autofac;
- using Bowin.Common.Log;
- using EMIS.CommonLogic.SystemServices;
- using EMIS.Entities;
- namespace EMIS.Services
- {
- #region 所有的服务工作接口 IServiceJob
- /// <summary>
- /// IServiceJob : 所有的服务工作接口
- /// </summary>
- public interface IServiceJob
- {
- string JobID { get; set; }
- string JobName { get; set; }
- Guid SchedulerID { get; set; }
- int MaxThreadSize { get; set; }
- bool IsDebug { get; set; }
- string CertFile { get; set; }
- void ExecuteJob();
- DateTime AllTimeBegin { get; set; }
- DateTime AllTimeEnd { get; set; }
- int AllUseSeconds { get; set; }
- string Desc { get; set; }
- }
- #endregion
- #region 所有Job的基类
- /// <summary>
- /// 所有Job的基类。
- /// </summary>
- public abstract class EAPServiceJob : IServiceJob
- {
- #region 实现IServiceJob接口
- private string _jobid = "";
- private string _jobname = "";
- private Guid _schedulerid = Guid.Empty;
- private int _MaxThreadSize = 1;
- private bool _isdubug = false;
- private string _certfile = "";
- DateTime _AllTimeBegin;
- DateTime _AllTimeEnd;
- int _AllUseSeconds;
- DateTime _OneScheduleTimeBegin;
- DateTime _OneScheduleTimeEnd;
- int _OneScheduleUseSeconds;
- bool _Successful;
- string _Desc;
- /// <summary>
- /// 任务ID
- /// </summary>
- public string JobID
- {
- get { return _jobid; }
- set { _jobid = value; }
- }
- /// <summary>
- /// 任务名称
- /// </summary>
- public string JobName
- {
- get { return _jobname; }
- set { _jobname = value; }
- }
- /// <summary>
- /// 执行ID
- /// </summary>
- public Guid SchedulerID
- {
- get { return _schedulerid; }
- set { _schedulerid = value; }
- }
- /// <summary>
- /// 子服务同时最大线程数
- /// </summary>
- public int MaxThreadSize
- {
- get { return _MaxThreadSize; }
- set { _MaxThreadSize = value; }
- }
- /// <summary>
- /// 是否调试状态
- /// </summary>
- public bool IsDebug
- {
- get { return _isdubug; }
- set { _isdubug = value; }
- }
- /// <summary>
- /// 证书文件
- /// </summary>
- public string CertFile
- {
- get { return this._certfile; }
- set { this._certfile = value; }
- }
- /// <summary>
- /// 总体执行开始时间
- /// </summary>
- public DateTime AllTimeBegin
- {
- get { return _AllTimeBegin; }
- set { _AllTimeBegin = value; }
- }
- /// <summary>
- /// 总体执行结束时间
- /// </summary>
- public DateTime AllTimeEnd
- {
- get { return _AllTimeEnd; }
- set { _AllTimeEnd = value; }
- }
- /// <summary>
- /// 总体服务执行耗时秒数
- /// </summary>
- public int AllUseSeconds
- {
- get { return _AllUseSeconds; }
- set { _AllUseSeconds = value; }
- }
- /// <summary>
- /// 单个服务执行开始时间
- /// </summary>
- public DateTime OneScheduleTimeBegin
- {
- get { return _OneScheduleTimeBegin; }
- set { _OneScheduleTimeBegin = value; }
- }
- /// <summary>
- /// 单个服务执行结束时间
- /// </summary>
- public DateTime OneScheduleTimeEnd
- {
- get { return _OneScheduleTimeEnd; }
- set { _OneScheduleTimeEnd = value; }
- }
- /// <summary>
- /// 单个服务执行耗时秒数
- /// </summary>
- public int OneScheduleUseSeconds
- {
- get { return _OneScheduleUseSeconds; }
- set { _OneScheduleUseSeconds = value; }
- }
- /// <summary>
- /// 是否执行成功
- /// </summary>
- public bool Successful
- {
- get { return _Successful; }
- set { _Successful = value; }
- }
- /// <summary>
- /// 执行结果备注信息
- /// </summary>
- public string Desc
- {
- get { return _Desc; }
- set { _Desc = value; }
- }
- #endregion
- #region 运行JOB
- public void RunJobOnce()
- {
- this.MyJob();
- }
- #endregion
- public virtual void ExecuteJob()
- {
- //起止配对;容易找起止。
- Guid tagID = Guid.NewGuid();
- try
- {
- this.Init();
- Desc = "服务【" + this._jobname + "】开始执行:{" + tagID.ToString() + "}";
- LogHelper.WriteLog(LogType.ServiceLog, Desc);
- //先置最后执行时间;防止多线程一次集中连续执行。
- using (var scop = Program.AutofacContainer.BeginLifetimeScope())
- {
- var ScheduleServices = scop.Resolve<IScheduleServices>();
- ScheduleServices.UpdateLastRun(SchedulerID);
- }
- this.MyJob();
- OneScheduleTimeEnd = System.DateTime.Now;
- TimeSpan ts = new TimeSpan();
- ts = OneScheduleTimeEnd - OneScheduleTimeBegin;
- OneScheduleUseSeconds = Convert.ToInt32(ts.TotalSeconds);
- Desc = "服务【" + this._jobname + "】结束执行;耗时:" + OneScheduleUseSeconds.ToString() + "秒。{" + tagID.ToString() + "}";
- LogHelper.WriteLog(LogType.ServiceLog, Desc);
- Successful = true;
- UpdateSchedulingLog(SchedulerID, JobID, OneScheduleTimeBegin, OneScheduleTimeEnd, OneScheduleUseSeconds,
- Successful, "执行成功");
- }
- catch (Exception err)
- {
- OneScheduleTimeEnd = System.DateTime.Now;
- Desc = "服务【" + this._jobname + "】执行异常:" + err.Message;
- TimeSpan ts = new TimeSpan();
- ts = OneScheduleTimeEnd - OneScheduleTimeBegin;
- OneScheduleUseSeconds = Convert.ToInt32(ts.TotalSeconds); //转换时间间隔为 秒
- LogHelper.WriteLog(LogType.ServiceLog, "服务【" + this._jobname + "】结束;耗时:" + OneScheduleUseSeconds.ToString() + "秒;{" + tagID.ToString() + "} \r\n 执行结果:\r\n " + Desc);
- Successful = true;
- UpdateSchedulingLog(SchedulerID, JobID, OneScheduleTimeBegin, OneScheduleTimeEnd, OneScheduleUseSeconds,
- Successful, "执行失败:" + err.Message);
- }
- finally
- {
- }
- }
- protected virtual bool Init()
- {
- Successful = true;
- AllTimeBegin = System.DateTime.Now;
- AllTimeEnd = System.DateTime.Now;
- AllUseSeconds = 0;
- OneScheduleTimeBegin = System.DateTime.Now;
- OneScheduleTimeEnd = System.DateTime.Now;
- OneScheduleUseSeconds = 0;
- Desc = "服务【" + this._jobname + "】开始执行:";
- return true;
- }
- protected abstract bool MyJob();
- #region 修改具体服务调度表中的执行信息,记录服务调度历史记录。
- /// <summary>
- /// 修改具体服务调度表中的执行信息,记录服务调度历史记录。
- /// </summary>
- public void UpdateSchedulingLog(Guid schedulerID, string jobID, DateTime scheduleTimeBegin, DateTime scheduleTimeEnd, int UseSeconds,
- bool successful, string desc)
- {
- try
- {
- using (var scop = Program.AutofacContainer.BeginLifetimeScope())
- {
- var ScheduleServices = scop.Resolve<IScheduleServices>();
- ScheduleServices.UpdateLastRunAndLoopNum(SchedulerID);
- Sys_ScheduleLog log = new Sys_ScheduleLog();
- log.scid = schedulerID;
- log.timeBegin = scheduleTimeBegin;
- log.timeEnd = scheduleTimeEnd;
- log.successful = successful;
- log.useSeconds = UseSeconds;
- log.Desc = desc;
- ScheduleServices.InsertLog(log);
- }
- }
- catch (Exception ce)
- {
- LogHelper.WriteLog(LogType.ServiceLog, "操作数据库异常:" + ce.Message);
- }
- }
- #endregion
- }
- #endregion
- #region ServiceWrapper的接口
- namespace MyEAPServiceWrapper
- {
- /// <summary>
- /// ServiceWrapper的接口。
- /// 开启多线程,并且控制每个子服务当前最多只有一个线程在执行;多个子服务可以同时执行;防止不同的子服务彼此相互堵塞。
- /// </summary>
- public interface IServiceWrapper
- {
- bool IsDebug { get; set; }
- bool Execute();
- }
- }
- #endregion
- #region EAPServiceWrapper
- namespace MyEAPServiceWrapper
- {
- /// <summary>
- /// ServiceWrapper的具体子服务执行。
- /// 开启多线程,并且控制每个子服务当前最多只有一个线程在执行;多个子服务可以同时执行;防止不同的子服务彼此相互堵塞。
- /// </summary>
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Data;
- public class ServiceWrapper : IServiceWrapper
- {
- #region 实现IServiceWrapper接口属性
- private bool _isdubug = false;
- DateTime _AllTimeBegin;
- DateTime _AllTimeEnd;
- int _AllUseSeconds;
- DateTime _OneScheduleTimeBegin;
- DateTime _OneScheduleTimeEnd;
- int _OneScheduleUseSeconds;
- bool _Successful;
- string _Desc;
- Guid SchedulerID = Guid.Empty;
- int MaxThreadSize = 1;
- string JobID = "";
- string JobName = "";
- string AssemName = "";
- string ClassName = "";
- /// <summary>
- /// 是否调试状态
- /// </summary>
- public bool IsDebug
- {
- get { return _isdubug; }
- set { _isdubug = value; }
- }
- /// <summary>
- /// 总体执行开始时间
- /// </summary>
- public DateTime AllTimeBegin
- {
- get { return _AllTimeBegin; }
- set { _AllTimeBegin = value; }
- }
- /// <summary>
- /// 总体执行结束时间
- /// </summary>
- public DateTime AllTimeEnd
- {
- get { return _AllTimeEnd; }
- set { _AllTimeEnd = value; }
- }
- /// <summary>
- /// 总体服务执行耗时秒数
- /// </summary>
- public int AllUseSeconds
- {
- get { return _AllUseSeconds; }
- set { _AllUseSeconds = value; }
- }
- /// <summary>
- /// 单个服务执行开始时间
- /// </summary>
- public DateTime OneScheduleTimeBegin
- {
- get { return _OneScheduleTimeBegin; }
- set { _OneScheduleTimeBegin = value; }
- }
- /// <summary>
- /// 单个服务执行结束时间
- /// </summary>
- public DateTime OneScheduleTimeEnd
- {
- get { return _OneScheduleTimeEnd; }
- set { _OneScheduleTimeEnd = value; }
- }
- /// <summary>
- /// 单个服务执行耗时秒数
- /// </summary>
- public int OneScheduleUseSeconds
- {
- get { return _OneScheduleUseSeconds; }
- set { _OneScheduleUseSeconds = value; }
- }
- /// <summary>
- /// 是否执行成功
- /// </summary>
- public bool Successful
- {
- get { return _Successful; }
- set { _Successful = value; }
- }
- /// <summary>
- /// 执行结果备注信息
- /// </summary>
- public string Desc
- {
- get { return _Desc; }
- set { _Desc = value; }
- }
- #endregion
- #region 子服务线程控制
- public class ThreadInfo
- {
- public int ManagedThreadId { get; set; }
- public string Name { get; set; }
- public bool IsAlive { get; set; }
- public DateTime StartTime { get; set; }
- }
- /// <summary>
- /// 存放当前正在执行的子服务线程信息
- /// </summary>
- static System.Collections.Generic.List<ThreadInfo> NowExecThreadsInfo = new System.Collections.Generic.List<ThreadInfo>();
- #endregion
- #region 整体控制执行服务
- /// <summary>
- /// 开启多线程,并且控制每个子服务当前最多只有一个线程在执行;多个子服务可以同时执行;防止不同的子服务彼此相互堵塞。
- /// </summary>
- /// <returns></returns>
- public bool Execute()
- {
- //AllTimeEnd = System.DateTime.Now;
- //Desc = "总体服务执行成功!";
- //TimeSpan ts = new TimeSpan();
- //ts = AllTimeEnd - AllTimeBegin;
- //AllUseSeconds = Convert.ToInt32(ts.TotalSeconds); //转换时间间隔为 秒
- //Log.WriteLog("总体服务结束;耗时:" + AllUseSeconds.ToString() + "秒; \r\n 执行结果:\r\n " + Desc);
- bool bResult = true;
- //string serverName = ConfigurationManager.AppSettings["ServerName"];
- var scheduleJobList = QureyScheduleJobs();
- foreach (var scheduleJob in scheduleJobList)
- {
- string sStartDate = scheduleJob.datebegin.ToString().Trim(); ;//20040707
- sStartDate = sStartDate.Substring(0, 4) + "-" + sStartDate.Substring(4, 2) + "-" + sStartDate.Substring(6, 2); //转换成2004-07-07
- DateTime tmpStartDate = System.Convert.ToDateTime(sStartDate);
- sStartDate = scheduleJob.dateend.ToString().Trim();
- sStartDate = sStartDate.Substring(0, 4) + "-" + sStartDate.Substring(4, 2) + "-" + sStartDate.Substring(6, 2); //转换成2004-07-07
- DateTime tmpEndDate = System.Convert.ToDateTime(sStartDate);
- int scinterval = scheduleJob.scinterval;
- /* D:天 H:小时 M:分钟 S:秒 */
- switch (scheduleJob.scmode.ToUpper())
- {
- case "D":
- scinterval = scheduleJob.scinterval * (60 * 60 * 24);
- //对于周期跨天的,要防止累计偏差而出现跳天现象(空出2分钟的柔韧空间值)。
- scinterval = scinterval - 120;
- break;
- case "H":
- scinterval = scheduleJob.scinterval * (60 * 60);
- break;
- case "M":
- scinterval = scheduleJob.scinterval * (60);
- break;
- //默认秒
- default:
- break;
- }
- this.SchedulerID = scheduleJob.scid;
- this.MaxThreadSize = 1;
- this.JobID = scheduleJob.Sys_ScheduleJob.jobid;
- this.JobName = scheduleJob.Sys_ScheduleJob.jobname;
- this.AssemName = scheduleJob.Sys_ScheduleJob.assemname;
- this.ClassName = scheduleJob.Sys_ScheduleJob.classname;
- //检查该项服务是否到了下次运行时间,如是则运行。
- if (this.CheckJobAllowRun(tmpStartDate, tmpEndDate, scinterval, scheduleJob.lastrun,
- scheduleJob.timefrom, scheduleJob.timeto))
- {
- //this.JobRun(tmpSchedulerID, tmpJobID,tmpServerName, tmpJobName, tmpAssemName, tmpClassName);
- System.Threading.Thread thread = new System.Threading.Thread(JobRun);
- thread.Start();
- //防止循环后再次获取数据库进行判断,而当前的验证还没有加入线程属性导致可能多1个子线程服务在运行;需要停顿一下。
- System.Threading.Thread.Sleep(3000);
- }
- }
- return bResult;
- }
- #endregion
- #region 检查是允许运行
- /// <summary>
- /// 检查任务是否允许运行
- /// </summary>
- /// <param name="StartDate"></param>
- /// <param name="EndDate"></param>
- /// <param name="SecondTiple"></param>
- /// <param name="LastUpdate"></param>
- /// <returns></returns>
- private bool CheckJobAllowRun(DateTime StartDate, DateTime EndDate, int SecondTiple, DateTime? LastUpdate, string StartTime, string EndTime)
- {
- DateTime nowday = new System.DateTime(System.DateTime.Now.Year, System.DateTime.Now.Month, System.DateTime.Now.Day);
- StartDate = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day);
- EndDate = new DateTime(EndDate.Year, EndDate.Month, EndDate.Day);
- if ((nowday >= StartDate) && (nowday <= EndDate))
- {
- if (InRunTimeRange(StartTime, EndTime))
- {
- if ((ReturnSecondFromDate(System.DateTime.Now) - ReturnSecondFromDate(LastUpdate)) >= SecondTiple)
- return true;
- else
- return false;
- }
- else
- return false;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 把日期转化为秒
- /// </summary>
- /// <param name="datetime1"></param>
- /// <returns></returns>
- private long ReturnSecondFromDate(DateTime? datetime1)
- {
- if (!datetime1.HasValue) return 0;
- return (long)((datetime1.Value.Year * 365 + datetime1.Value.DayOfYear) * 24 * 60 + datetime1.Value.Hour * 60 + datetime1.Value.Minute) * 60 + datetime1.Value.Second;
- }
- private bool InRunTimeRange(string StartTime, string EndTime)
- {
- int mHour = System.DateTime.Now.Hour;
- int mMinute = System.DateTime.Now.Minute;
- int mSecond = System.DateTime.Now.Second;
- string[] splStartTime = StartTime.Split(':');
- int mStartHour = Convert.ToInt32(splStartTime[0]);
- int mStartMinute = Convert.ToInt32(splStartTime[1]);
- int mStartSecond = Convert.ToInt32(splStartTime[2]);
- string[] splEndTime = EndTime.Split(':');
- int mEndHour = Convert.ToInt32(splEndTime[0]);
- int mEndMinute = Convert.ToInt32(splEndTime[1]);
- int mEndSecond = Convert.ToInt32(splEndTime[2]);
- int mCurrent = mHour * 60 * 60 + mMinute * 60 + mSecond;
- int mStart = mStartHour * 60 * 60 + mStartMinute * 60 + mStartSecond;
- int mEnd = mEndHour * 60 * 60 + mEndMinute * 60 + mEndSecond;
- if (mCurrent >= mStart && mCurrent <= mEnd)
- return true;
- return false;
- }
- #endregion
- #region 运行具体某个Job
- /// <summary>
- /// 运行服务工作,不返回错误以免将其他的工作也停止
- /// private void JobRun(string schedulerID, string jobID,string serverName, string jobName, string assemName, string className)
- /// </summary>
- /// <param name="SqlConn"></param>
- /// <param name="JobName"></param>
- /// <param name="ClassName"></param>
- private void JobRun()
- {
- Guid schedulerID = SchedulerID;
- int maxThreadSize = MaxThreadSize;
- string jobID = JobID;
- string jobName = JobName;
- string assemName = AssemName;
- string className = ClassName;
- bool thisTimeNeedDo = true;
- ThreadInfo threadInfo = new ThreadInfo();
- try
- {
- //判断检查该项服务对应的线程是否在运行。
- System.Threading.Thread currentSubServiceThread = System.Threading.Thread.CurrentThread;
- currentSubServiceThread.Name = className;
- //启动时间在6个钟内的线程才有效
- var currentSubServices = (from a in NowExecThreadsInfo
- where a.Name == className
- && a.StartTime > DateTime.Now.AddHours(-6)
- select new ThreadInfo
- {
- ManagedThreadId = a.ManagedThreadId,
- Name = a.Name,
- IsAlive = a.IsAlive,
- StartTime = a.StartTime
- }
- ).ToList();
- int currentSubServiceNum = currentSubServices.Count;
- LogHelper.WriteLog(LogType.ServiceLog, "当前【" + className + "】有个(" + currentSubServiceNum.ToString() + ")线程在执行。最大线程数:" + maxThreadSize.ToString() + ";时间:" + DateTime.Now.ToString());
- if (currentSubServiceNum >= maxThreadSize)
- {
- thisTimeNeedDo = false;
- LogHelper.WriteLog(LogType.ServiceLog, "当前【" + className + "】正已经有个(" + currentSubServiceNum.ToString() + ")线程在执行,本次跳过激发执行。" + DateTime.Now.ToString());
- }
- if (thisTimeNeedDo)
- {
- //加线程子服务信息
- threadInfo.ManagedThreadId = currentSubServiceThread.ManagedThreadId;
- threadInfo.Name = currentSubServiceThread.Name;
- threadInfo.IsAlive = currentSubServiceThread.IsAlive;
- threadInfo.StartTime = DateTime.Now;
- NowExecThreadsInfo.Add(threadInfo);
- string fullClassName = "";
- Assembly assem = Assembly.Load(assemName);
- if (className.IndexOf(".") > 0)
- {
- fullClassName = className;
- }
- else
- {
- fullClassName = assemName + "." + className;
- }
- //Log.WriteLog("TestHere01 " + fullClassName);
- Type classType = assem.GetType(fullClassName);
- IServiceJob fss = (IServiceJob)System.Activator.CreateInstance(classType);
- fss.SchedulerID = schedulerID;
- fss.JobID = jobID;
- fss.JobName = jobName;
- fss.IsDebug = this._isdubug;
- fss.CertFile = ConfigurationManager.AppSettings["CertFile"];
- fss.ExecuteJob(); //运行Job
- }
- }
- catch (Exception ce)
- {
- LogHelper.WriteLog(LogType.ServiceLog, "服务【" + jobName + "】执行异常:" + ce.Message);
- }
- finally
- {
- if (thisTimeNeedDo)
- {
- //处理完毕后清除线程子服务信息
- NowExecThreadsInfo.Remove(threadInfo);
- }
- }
- }
- #endregion
- #region 获取总体服务信息;然后处理那些需要执行的各个具体服务。
- /// <summary>
- /// 获取总体服务信息;然后处理那些需要执行的各个具体服务。
- /// </summary>
- public List<Sys_Scheduling> QureyScheduleJobs()
- {
- try
- {
- using (var scop = Program.AutofacContainer.BeginLifetimeScope())
- {
- var ScheduleServices = scop.Resolve<IScheduleServices>();
- return ScheduleServices.GetJobList();
- }
- }
- catch (Exception ce)
- {
- LogHelper.WriteLog(LogType.ServiceLog, "操作数据库异常:" + ce.Message);
- }
- finally
- {
- }
- return new List<Sys_Scheduling>();
- }
- #endregion
- }
- #endregion
- }
- }
|