using System;
using System.ComponentModel;
using System.Xml;
using System.Data;
using System.Reflection;
using System.Configuration;
using Autofac;
using Bowin.Common.Log;
using EMIS.CommonLogic.SystemServices;
using EMIS.Entities;
namespace EMIS.Services
{
#region 所有的服务工作接口 IServiceJob
///
/// IServiceJob : 所有的服务工作接口
///
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的基类
///
/// 所有Job的基类。
///
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;
///
/// 任务ID
///
public string JobID
{
get { return _jobid; }
set { _jobid = value; }
}
///
/// 任务名称
///
public string JobName
{
get { return _jobname; }
set { _jobname = value; }
}
///
/// 执行ID
///
public Guid SchedulerID
{
get { return _schedulerid; }
set { _schedulerid = value; }
}
///
/// 子服务同时最大线程数
///
public int MaxThreadSize
{
get { return _MaxThreadSize; }
set { _MaxThreadSize = value; }
}
///
/// 是否调试状态
///
public bool IsDebug
{
get { return _isdubug; }
set { _isdubug = value; }
}
///
/// 证书文件
///
public string CertFile
{
get { return this._certfile; }
set { this._certfile = value; }
}
///
/// 总体执行开始时间
///
public DateTime AllTimeBegin
{
get { return _AllTimeBegin; }
set { _AllTimeBegin = value; }
}
///
/// 总体执行结束时间
///
public DateTime AllTimeEnd
{
get { return _AllTimeEnd; }
set { _AllTimeEnd = value; }
}
///
/// 总体服务执行耗时秒数
///
public int AllUseSeconds
{
get { return _AllUseSeconds; }
set { _AllUseSeconds = value; }
}
///
/// 单个服务执行开始时间
///
public DateTime OneScheduleTimeBegin
{
get { return _OneScheduleTimeBegin; }
set { _OneScheduleTimeBegin = value; }
}
///
/// 单个服务执行结束时间
///
public DateTime OneScheduleTimeEnd
{
get { return _OneScheduleTimeEnd; }
set { _OneScheduleTimeEnd = value; }
}
///
/// 单个服务执行耗时秒数
///
public int OneScheduleUseSeconds
{
get { return _OneScheduleUseSeconds; }
set { _OneScheduleUseSeconds = value; }
}
///
/// 是否执行成功
///
public bool Successful
{
get { return _Successful; }
set { _Successful = value; }
}
///
/// 执行结果备注信息
///
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();
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 修改具体服务调度表中的执行信息,记录服务调度历史记录。
///
/// 修改具体服务调度表中的执行信息,记录服务调度历史记录。
///
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();
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
{
///
/// ServiceWrapper的接口。
/// 开启多线程,并且控制每个子服务当前最多只有一个线程在执行;多个子服务可以同时执行;防止不同的子服务彼此相互堵塞。
///
public interface IServiceWrapper
{
bool IsDebug { get; set; }
bool Execute();
}
}
#endregion
#region EAPServiceWrapper
namespace MyEAPServiceWrapper
{
///
/// ServiceWrapper的具体子服务执行。
/// 开启多线程,并且控制每个子服务当前最多只有一个线程在执行;多个子服务可以同时执行;防止不同的子服务彼此相互堵塞。
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Data;
using System.Collections;
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 = "";
///
/// 是否调试状态
///
public bool IsDebug
{
get { return _isdubug; }
set { _isdubug = value; }
}
///
/// 总体执行开始时间
///
public DateTime AllTimeBegin
{
get { return _AllTimeBegin; }
set { _AllTimeBegin = value; }
}
///
/// 总体执行结束时间
///
public DateTime AllTimeEnd
{
get { return _AllTimeEnd; }
set { _AllTimeEnd = value; }
}
///
/// 总体服务执行耗时秒数
///
public int AllUseSeconds
{
get { return _AllUseSeconds; }
set { _AllUseSeconds = value; }
}
///
/// 单个服务执行开始时间
///
public DateTime OneScheduleTimeBegin
{
get { return _OneScheduleTimeBegin; }
set { _OneScheduleTimeBegin = value; }
}
///
/// 单个服务执行结束时间
///
public DateTime OneScheduleTimeEnd
{
get { return _OneScheduleTimeEnd; }
set { _OneScheduleTimeEnd = value; }
}
///
/// 单个服务执行耗时秒数
///
public int OneScheduleUseSeconds
{
get { return _OneScheduleUseSeconds; }
set { _OneScheduleUseSeconds = value; }
}
///
/// 是否执行成功
///
public bool Successful
{
get { return _Successful; }
set { _Successful = value; }
}
///
/// 执行结果备注信息
///
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; }
}
///
/// 存放当前正在执行的子服务线程信息
///
static System.Collections.Generic.List NowExecThreadsInfo = new System.Collections.Generic.List();
#endregion
#region 整体控制执行服务
///
/// 开启多线程,并且控制每个子服务当前最多只有一个线程在执行;多个子服务可以同时执行;防止不同的子服务彼此相互堵塞。
///
///
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 检查是允许运行
///
/// 检查任务是否允许运行
///
///
///
///
///
///
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;
}
}
///
/// 把日期转化为秒
///
///
///
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
///
/// 运行服务工作,不返回错误以免将其他的工作也停止
/// private void JobRun(string schedulerID, string jobID,string serverName, string jobName, string assemName, string className)
///
///
///
///
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 获取总体服务信息;然后处理那些需要执行的各个具体服务。
///
/// 获取总体服务信息;然后处理那些需要执行的各个具体服务。
///
public List QureyScheduleJobs()
{
try
{
using (var scop = Program.AutofacContainer.BeginLifetimeScope())
{
var ScheduleServices = scop.Resolve();
return ScheduleServices.GetJobList();
}
}
catch (Exception ce)
{
LogHelper.WriteLog(LogType.ServiceLog, "操作数据库异常:" + ce.Message);
}
finally
{
}
return new List();
}
#endregion
}
#endregion
}
}