asp.net 计划任务管理程序实现,多线程任务加载 |
本文标签:asp.net,计划任务 asp.net下实现可以将计划任务的方法放在global里,使用一个统一的任务管理类来管理各种任务的执行,做到并行不悖! 下面是我写的一个方法,希望起个抛砖引玉的作用!大家一起学习下: 第一步定义一个接口,用来规范任务必须要实现的动作,该接口只有一个方法(简单起见): 复制代码 代码如下: /// <summary> /// 工作单元接口,定义一个计划任务必须完成的工作 /// </summary> public interface IScheduledTask { /// <summary> /// 任务执行 /// </summary> void Execute(); } 第二步,定义一个类,用来管理计划任务的执行和关闭: 复制代码 代码如下: /// <summary> /// 用来执行计划任务的基本对象 /// </summary> public class ScheduledTask { private static readonly ScheduledTask _ScheduledTask = null; private Timer UpdateTimer = null; /// <summary> /// 间隔时间,单位为毫秒 /// </summary> private int interval = 10 * 1000; /// <summary> /// 间隔时间,单位为毫秒 /// </summary> public int Interval { get { return this.interval; } set { this.interval = value; } } /// <summary> /// 任务是否完成标志 /// </summary> private int _IsRunning; /// <summary> /// 静态构造函数,保证实例的唯一性 /// </summary> static ScheduledTask() { _ScheduledTask = new ScheduledTask(); } /// <summary> /// 任务队列 /// </summary> private ArrayList tasks = new ArrayList(); /// <summary> /// 任务队列 /// </summary> public ArrayList Tasks { get { return tasks; } } /// <summary> /// 返回任务实例 /// </summary> /// <returns></returns> public static ScheduledTask Instance() { return _ScheduledTask; } /// <summary> /// 执行任务 /// </summary> public void Start() { if (UpdateTimer == null) { UpdateTimer = new Timer(new TimerCallback(UpdateTimerCallback), null, interval, interval); } } /// <summary> /// 任务处理 /// </summary> /// <param name="sender"></param> private void UpdateTimerCallback(object sender) { if (Interlocked.Exchange(ref _IsRunning, 1) == 0) { try { //执行多个任务 foreach (IScheduledTask task in Tasks) { ThreadStart myThreadDelegate = new ThreadStart(task.Execute); Thread myThread = new Thread(myThreadDelegate); myThread.Start(); } } catch (Exception ex) { //错误处理 CreateLog(ex.Message, true); } finally { Interlocked.Exchange(ref _IsRunning, 0); } } } /// <summary> /// 取消任务 /// </summary> public void Stop() { if (UpdateTimer != null) { UpdateTimer.Dispose(); UpdateTimer = null; } } /// <summary> /// 记录日志至文本文件 /// </summary> /// <param name="message"></param> /// <param name="iserror"></param> public static void CreateLog(string message, bool iserror) { DateTime dt = DateTime.Now; int y = dt.Year;//当前的年份 int m = dt.Month;//当前的月份 string root = HttpRuntime.AppDomainAppPath; root += "ScheduledTaskLogs"; if (!File.Exists(root)) Directory.CreateDirectory(root); string dir_y = root + "\\" + y.ToString(); string dir_m = dir_y + "\\" + m.ToString(); string err = iserror ? "_taskerror" : "_task"; string dirOk = dir_m + "\\" + dt.Year + dt.Month + dt.Day + err + ".txt"; //以当前年份为名创建新目录 if (!File.Exists(dir_y)) Directory.CreateDirectory(dir_y); //以当前月份为名创建新目录 if (!File.Exists(dir_m)) Directory.CreateDirectory(dir_m); string err1 = iserror ? "错误" : ""; if (File.Exists(dirOk)) { StreamWriter sr = new StreamWriter(dirOk, true, Encoding.Default); lock (sr) { sr.WriteLine(); sr.WriteLine("--------------计划任务" + err1 + "日志-----------------------------------------------------------------------"); sr.WriteLine(err1 + "时间: " + DateTime.Now.ToString()); sr.WriteLine("详细内容: " + message); sr.WriteLine("--------------------------------------------------------------------------------------------"); } sr.Close(); sr.Dispose(); } else { StreamWriter sr = new StreamWriter(dirOk, false, Encoding.Default); lock (sr) { sr.WriteLine(); sr.WriteLine("--------------计划任务" + err1 + "日志-----------------------------------------------------------------------"); sr.WriteLine(err1 + "时间: " + DateTime.Now.ToString()); sr.WriteLine("详细内容: " + message); sr.WriteLine("--------------------------------------------------------------------------------------------"); } sr.Close(); sr.Dispose(); } } } 第三步,定义要做的动作处理类,继承第一步定义的接口,下面的例子是一个定时邮件发送程序,在规定的时间段执行邮件发送: 复制代码 代码如下: /// <summary> /// 计划任务--定时发送邮件 /// </summary> public class Task_MailSend : IScheduledTask { public void Execute() { string nw = DateTime.Now.ToString("HH"); int hh = 0; if (!Int32.TryParse(nw, out hh)) { return; } //每天11-13点发送邮件 if (hh < 10 || hh > 17) { ScheduledTask.CreateLog("没到发送时间", true); return; } DataTable dt = GetOrderedUser(); int num = dt.Rows.Count; if (num == 0) { ScheduledTask.CreateLog("目前没有用户订阅", true); return; } /* mail发送程序 。 。 。 */ } 好了,执行上面三步后,剩下的工作就交给global来做了! 复制代码 代码如下: <script runat="server"><!-- void Application_Start(object sender, EventArgs e) { // 在应用程序启动时运行的代码 //WildRen.Common是我这里的命名空间 WildRen.Common.ScheduledTask.Instance().Interval = 12 * 60 * 60000;//设置计划任务执行时间间隔 WildRen.Common.ScheduledTask.Instance().Tasks.Add(new Task_MailSend());//向计划任务管理程序添加要执行的动作 WildRen.Common.ScheduledTask.Instance().Start();//启动任务 } void Application_End(object sender, EventArgs e) { // 在应用程序关闭时运行的代码 WildRen.Common.ScheduledTask.Instance().Stop(); } // --></script> 如果使用ajax连接此管理类模拟客户端timer事件经行处理也是可以的!当然方法不是唯一的,此程序可能存在一些不足之处,欢迎大家指正! |