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事件经行处理也是可以的!当然方法不是唯一的,此程序可能存在一些不足之处,欢迎大家指正!