在业务复杂的应用程序中,有时候会要求一个或者多个任务在一定的时间或者一定的时间间隔内计划进行,比如定时备份或同步数据库,定时发送电子邮件等,我们称之为计划任务。实现计划任务的方法也有很多,可以采用SQLAgent执行存储过程来实现,也可以采用Windows任务调度程序来实现,也可以使用Windows服务来完成我们的计划任务,这些方法都是很好的解决方案。但是,对于Web应用程序来说,这些方法实现起来并不是很简单的,主机服务提供商或者不能直接提供这样的服务,或者需要你支付许多额外的费用。 本文就介绍一个直接在Web应用程序中使用的简单的方法,这个方法不需要任何额外的配置即可轻松实现。

由于ASP.NET站点是作为Web应用程序运行的,它并不受线程的限制,因此我们可以非常方便地在Application_Start和Application_End事件中建立和销毁一个计划任务。下面就简单介绍一下在Web站点实现计划任务的方法。我们的例子是定时往文件里添加信息,作为例子,这里把当前的时间定时地写入文件中。

一个计划任务的工作单元称之为一个任务(Job),下面的代码描述了对所有任务都可以被调度引擎计划执行的一个通用的接口,这里的每个任务实现了Execute方法,供调度引擎进行调用:

     public interface ISchedulerJob
     {
      void Execute();
     }
如前所述,我们的例子是实现往文件写如字符日期,下面就是实现这一任务的方法:

     public class SampleJob : ISchedulerJob
     {
      public void Execute()
      {
       //文件保存的物理路径,CSTest为虚拟目录名称,F:InetpubwwwrootCSTest为物理路径
       string p = @"F:InetpubwwwrootCSTest";
       //我们在虚拟目录的根目录下建立SchedulerJob文件夹,并设置权限为匿名可修改,
       //SchedulerJob.txt就是我们所写的文件
       string FILE_NAME = p+ "/SchedulerJob/SchedulerJob.txt";
       //取得当前服务器时间,并转换成字符串
       string c = System.DateTime.Now.ToString("yyyy-mm-dd hh:MM:ss");
       //标记是否是新建文件的标量
       bool flag = false;
       //如果文件不存在,就新建该文件
       if (!File.Exists(FILE_NAME))
       {
        flag = true;
        StreamWriter sr = File.CreateText(FILE_NAME);
        sr.Close();
       }
       //向文件写入内容
       StreamWriter x = new StreamWriter(FILE_NAME,true,System.Text.Encoding.Default);
       if(flag) x.Write("计划任务测试开始:");
       x.Write(" "+c);
       x.Close();
      }
     }
接下来,我们建立一个配置对象,告诉调度引擎执行什么任务和执行的时间间隔。

     public class SchedulerConfiguration
     {
      //时间间隔
      private int sleepInterval;
      //任务列表
      private ArrayList jobs = new ArrayList();

      public int SleepInterval { get { return sleepInterval; } }
      public ArrayList Jobs { get { return jobs; } }

      //调度配置类的构造函数
      public SchedulerConfiguration(int newSleepInterval)
      {
       sleepInterval = newSleepInterval;
      }
     }
下面就是调度引擎,定时执行配置对象的任务

     public class Scheduler
     {
      private SchedulerConfiguration configuration = null;

      public Scheduler(SchedulerConfiguration config)
      {
       configuration = config;
      }

      public void Start()
      {
       while(true)
       {
        //执行每一个任务
        foreach(ISchedulerJob job in configuration.Jobs)
        {
         ThreadStart myThreadDelegate = new ThreadStart(job.Execute);
         Thread myThread = new Thread(myThreadDelegate);
         myThread.Start();
         Thread.Sleep(configuration.SleepInterval);
        }
       }
      }
     }
所有的准备工作已经完成,下面就是激活引擎的工作了。为了让我们的任务计划执行,我们在Global.asax.cs文件里的Applicatio_Start和Application_End里进行建立和销毁工作,首先建立一个调度进程运行的线程,我们这里的运行间隔时间为3秒钟。

  public System.Threading.Thread schedulerThread = null;
  protected void Application_Start(Object sender, EventArgs e)
  {
    SchedulerConfiguration config =  new SchedulerConfiguration(1000*3);
    config.Jobs.Add(new SampleJob());
    Scheduler scheduler = new Scheduler(config);
    System.Threading.ThreadStart myThreadStart =  new System.Threading.ThreadStart(scheduler.Start);
    System.Threading.Thread schedulerThread = new System.Threading.Thread(myThreadStart);
    schedulerThread.Start();
  }
最后还需要在程序退出时进行销毁:

  protected void Application_End(Object sender, EventArgs e)
  {
    if (null != schedulerThread)
    {
      schedulerThread.Abort();
    }
  }
好了,在VS.NET里建立一个C#的Web应用程序工程,建立TaskScheduler.cs类,并修改相应的Global.asax.cs文件。为了能看到效果,我们再建立一个表单WebForm1.aspx,定时刷新来检查我们所记录的数据:

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
     Inherits="CSTest.WebForm1" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
      <HEAD>
        <title>在Web应用程序中执行计划任务的例子</title>
        <meta http-equiv="refresh" content="10">
      </HEAD>
      <body MS_POSITIONING="GridLayout">
        <form id="Form1" method="post" runat="server">
          <iframe style="width:100%;height:100%" src="SchedulerJob/SchedulerJob.txt"></iframe>
        </form>
      </body>
    </HTML>
对工程进行编译并运行,就可以看到结果了,结果如下:

        计划任务测试开始:
        2003-13-10 11:08:15
        2003-13-10 11:08:18
        2003-13-10 11:08:21
        2003-13-10 11:08:24
        2003-13-10 11:08:27
        2003-13-10 11:08:30
需要说明的是,以上只是在Web应用程序中执行计划任务的简单例子,对于多个任务来说,需要在不同的线程内进行工作,对计划的安排也是很简单的,实际还需要站点堵塞,当机的情况。另外这里也没有进行错误的处理等工作,相信大家会写出更加完美的代码的。

在Web应用程序中执行计划任务(多线程)的更多相关文章

  1. Java嵌入式数据库H2学习总结(二)——在Web应用程序中使用H2数据库

    一.搭建测试环境和项目 1.1.搭建JavaWeb测试项目 创建一个[H2DBTest]JavaWeb项目,找到H2数据库的jar文件,如下图所示: H2数据库就一个jar文件,这个Jar文件里面包含 ...

  2. Asp.NetCore Web应用程序中的请求管道和中间件

    你是否会迷惑当我们请求一个ASP.NetWeb应用程序以后,它是怎么处理这些请求的,后台是怎么工作的,今天就讲一下Asp.NetCore Web应用程序中的请求处理过程. 上一节,我们讲到,Start ...

  3. 在 ASP.NET MVC Web 应用程序中输出 RSS Feeds

    RSS全称Really Simple Syndication.一些更新频率较高的网站可以通过RSS让订阅者快速获取更新信息.RSS文档需遵守XML规范的,其中必需包含标题.链接.描述信息,还可以包含发 ...

  4. 5.把报表集成到Web应用程序中-生成网页和导出两种方式

    转自:https://wenku.baidu.com/view/104156f9770bf78a65295462.html 第四部分,把报表集成到Web应用程序中 用MyEclipse新建一个Web ...

  5. Delphi 如何在程序中执行动态生成的Delphi代码

    如何在程序中执行动态生成的Delphi代码 经常发现有人提这类问题,或者提问内容最后归结成这种问题 前些阵子有位高手写了一个“执行动态生成的代码”,这是真正的高手,我没那种功力,我只会投机取巧. 这里 ...

  6. 如何在程序中执行动态生成的Delphi代码

    如何在程序中执行动态生成的Delphi代码 经常发现有人提这类问题,或者提问内容最后归结成这种问题 前些阵子有位高手写了一个“执行动态生成的代码”,这是真正的高手,我没那种功力,我只会投机取巧. 这里 ...

  7. Web 应用程序中的安全向量 – ASP.NET MVC 4 系列

           Web 程序运行在标准的.基于文本的协议(HTTP 和 HTML)之上,所以特别容易受到自动攻击的伤害.本章主要介绍黑客如何滥用应用程序,以及针对这些问题的应对措施.   威胁:跨站脚本 ...

  8. 在web应用程序中使用MemcachedClient

    本文来自:http://www.cnblogs.com/yukaizhao/archive/2008/11/10/memcached_client_usage.html 一. 背景: 在大访问量的we ...

  9. 3、Web应用程序中的安全向量 -- cookie盗窃

    作为用户,为了防止cookie盗窃,可以在浏览器设置中选择"禁用cookie",但是这样做很可能导致在访问某个站点的时候弹出警告"该站点必须使用cookie". ...

随机推荐

  1. mysql 日期 字符串 时间戳转换

    #时间转字符串 select date_format(now(), '%Y-%m-%d'); -02-27 #时间转时间戳 select unix_timestamp(now()); #字符串转时间 ...

  2. CentOS 7下软阵列的创建

    硬阵列和软阵列没有什么可比性,毕竟应用的场景不一样,比如硬阵列性能强劲,有额外的内存支持缓存使其更快,但也有缺点,以硬盘为个数,且如果其中某个硬盘的容量不齐,那么会以最小的容量为准,体现出硬阵列的不灵 ...

  3. github入门教程:第一步

    [git教程] 以前在网上找过一些,见 http://www.wojilu.com/Forum1/Topic/702  我自己会一边学,一边写教程,过程中有不明白的,会跟大家请教交流.   ----- ...

  4. Magent搭建Memcached集群

    原文地址:http://ultrasql.blog.51cto.com/9591438/1636374 Memcached集群介绍 由于Memcached服务器与服务器之间没有任何通讯,并且不进行任何 ...

  5. 读写文件:每次读入大文件里的一行、读写.CSV文件

    读文件: 传统的读法.所有读出,按行处理: fp=open("./ps.txt", "r"); alllines=fp.readlines(); fp.clos ...

  6. CRM上线之路 走上了CRM实施顾问-第12天上班 -第三周

    今天是周五,<CRM初期需求说明>是经理们商讨的,总共2张纸,根据两次会议,我写了<CRM需求说明>总共18面. 这是这周的工作汇报,其实,报告是我一天内写出来的,中午饭都没吃 ...

  7. Unity3D实践系列02,查看Scene窗口物体

    删除"Hierarchy"窗口中的"Directional Light". 把鼠标放在"Scene"窗口,滑动鼠标滚轮,可以对"S ...

  8. 窗体的Alpha通道透明色支持

    参考: http://www.delphibbs.com/delphibbs/dispq.asp?lid=2190768 Windows 2000后,为了支持类似MAC界面的Alpha通道混合效果,提 ...

  9. ListBox使用

    一.什么是ListBox? ListBox 是一个显示项集合的控件.一次可以显示 ListBox 中的多个项. ListBox继承自ItemsControl,可以使用Items或者ItemsSourc ...

  10. Property's synthesized getter follows Cocoa naming convention for returning

    Property's synthesized getter follows Cocoa naming convention for returning.   今天早上在整理代码的时候发现了如上警告. ...