65.9K
CodeProject 正在变化。 阅读更多。
Home

计划任务 Web 服务

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (9投票s)

2007年11月23日

CPOL

7分钟阅读

viewsIcon

129815

downloadIcon

2501

一个充当任务调度器的 Web 服务。

引言

例如,假设您必须在每天上午 8 点到晚上 8 点之间每小时计算数据库中某些字段的值,但您无法完全控制运行您的 Web 应用程序的服务器;这是一个常见场景,我的项目将为您提供实现此工作所需的工具。

为 Web 应用程序安排任务并不总是那么容易。如果我们完全控制主机服务器,那就不是问题,但有时我们没有,所以我们不能做一些像这样简单的事情:创建一个控制台应用程序来执行我们 Web 应用程序所需的任务,然后将编译好的 EXE 添加到服务器的计划任务列表中。

请允许我提醒您,Web 应用程序的工作方式与 Windows 应用程序不同;如果我们要保持 Web 应用程序的活动状态,就必须定期向其发送请求。

背景

这里是另一个基于 Web 的调度器——它使用不同的方法来解决相同的问题。本文中的示例代码包含了您实现和管理自己的任务并将其添加到调度器服务所需的一切。

与另一篇文章最重要的区别之一是,此代码使用 Web 服务,因此您可以与任何应用程序集成,并且由于它使用基类,因此强制任务的实现遵循某种模式。

Using the Code

示例代码包含 6 个项目

  • CsharpTask,此项目包含一个用 C# 编写的示例任务
  • SchedulerService.Core,此项目包含任务基类,继承自此类以实现您自己的任务
  • SchedulerService.Entities,此项目包含一个表示计划任务的数据集,也包含一些常量
  • SchedulerService.KeepAlive,此项目是一个控制台应用程序,它会调用 Web 服务,定期运行此应用程序以确保调度器将保持运行
  • SchedulerService.UI,此项目包含几个 Windows 窗体,用于管理在 Web 服务上运行的计划任务
  • WS.Scheduler,这是项目的核心,这里实现了运行计划任务所需的所有功能

如果您只想按原样使用服务并希望实现自己的任务

  • 在您的 Web 服务器上设置 WS.Scheduler Web 服务
  • 在 Visual Studio 中创建一个新的类库项目(无论使用何种语言)
  • 添加对 SchedulerService.Core 项目的引用
  • 创建您的类并使其继承自基类 Task
  • 实现三个必需的方法 ExecuteLogEntryCancelTask(稍后会详细介绍)
  • 编译您的项目并将 DLL 文件添加到 Web 服务的 bin 文件夹
  • 如果需要,配置 SchedulerService.UI.exe.config 文件,这是 SchedulerService.UI 项目的 app.config 文件。您可能需要配置调度器服务运行的 URL,默认位置是:https:///Scheduler/Scheduler.asmx
  • 运行 UI 项目并添加您的任务
  • 现在您的任务已准备好运行,请定期调用您的 Web 服务以使其保持活动状态,您可以使用随附的控制台应用程序,您还需要在 app.config 中设置 Web 服务的 URL。

如何创建新任务

要创建可在服务中调度的任务,您必须用您喜欢的语言创建一个类库项目,然后添加对 SchedulerService.Core 项目的引用,并创建您的类并使其继承自 Task 基类。在添加任何自定义代码之前,您的类实现必须如下所示

C#
using System;
using System.Collections.Generic;
using System.Text;

namespace CsharpTask
{
    class MyTask : SchedulerService .Core .Task
    {

        public override void Execute()
        {
          throw new Exception("The method or operation is not implemented."); 
        }

        public override void CancelTask(string Message)
        {
          throw new Exception("The method or operation is not implemented.");
        }

        public override void LogEntry(string Entry)
        {
          throw new Exception("The method or operation is not implemented.");
        }
    }
}

VB.NET
       
Public Class MyTask
    Inherits SchedulerService.Core.Task


    Public Overrides Sub CancelTask(Optional ByVal Message As String = "")

    End Sub

    Public Overrides Sub Execute()

    End Sub

    Public Overrides Sub LogEntry(ByVal Entry As String)

    End Sub
    
End Class

您真正需要实现的代码是类的 Execute 方法。LogEntryCancelTask 方法的实现是可选的——如果您确实需要,请编写代码。

在代码中使用 Try/Catch 块是一个好习惯。Task 类有一个名为 AbortAfter 的属性——此属性用于在任务在 X 分钟后仍未完成时中止任务。如果您打算使用此功能,您将需要实现一个 Try/Catch 块,因为当任务中止时,它会引发 System.Threading.ThreadAbortException。此外,您必须在任务完成后运行 RaiseTaskFinishedEvent 方法,否则调度器将无法正常工作。如果您在代码中捕获到异常,您可以使用 RaiseTaskExceptionEvent 来停止和禁用任务,同时您查找异常的原因。以下是一个完整的 Execute 方法模板

    C#
    /// <sumary>


    /// Execute method

    /// </sumary>

    public override void Execute()
    {
        try
        {
            //Task Code goes here


            //Raise the finished event

            base.RaiseTaskFinishedEvent(this.TaskID, DateTime.Now);
        }
        catch (System.Threading.ThreadAbortException ex)
        {
            //Do nothing, this exception is thrown when the task  is

            //cancelled

            //But you have to catch this kind of exception, otherwise the 

            //task will not be marked as Aborted

        }
        catch (System.Exception ex)
        { 
            //Raise the exception event

            base.RaiseTaskExceptionEvent(this.TaskID, DateTime.Now,ex);
        }
    }

    VB.NET
    ''' <sumary>

    ''' Execute method

    ''' </sumary>

    Public Overrides Sub Execute()
        Try
            'Task Code goes here


            'Rasie the finished event

            MyBase.RaiseTaskFinishedEvent(Me.TaskID, DateTime.Now)
        Catch ex As System.Threading.ThreadAbortException
            'Do nothing, this exception is thrown when the task  is cancelled

            'But you have to catch this kind of exception, otherwise the

            'task will not be marked as Aborted

        Catch ex As Exception
            'Raise the exception event

            MyBase.RaiseTaskExceptionEvent(Me.TaskID, DateTime.Now, ex)
        End Try
    End Sub

示例代码包含两个测试类,VB.NET(与 Web 服务在同一项目中)和 C#(在一个单独的项目中),它们都做同样的事情:它们向日志文件写入一些条目。此外,它们还有代码,因此您可以测试 AbortAfter 功能。如果任务定义了一个值,它将进入无限循环(当然,仅用于测试目的)。

这就是您实现自己的任务所需知道的一切。

调度器服务如何工作

我不会在这里详细介绍调度器服务的工作原理,我只会概述 WS.Scheduler 项目中的一些代码文件。

调度器服务具有以下可用于管理服务的方法

    GetTaskList, this method returns a list of all scheduled tasks in the 
                 Service.
    AddTask, this method is used to add a new task to the Scheduler Service.
    DeleteTask, used to delete a task.
    UpdateTaskList, use this method to update the scheduled tasks.
    RunTasksNow, used to run a task now.
    CancelTask, this method stops the execution of a task.
    GetAvailableTasks, return a list of all available classes that inherit
                       from the 'Task' base class. this method will look in
                       all assemblies in the /bin folder of the Web Service.
    KeepAlive, you can call this method to keep the Web Service running.

调度器服务在 Global.asax 中包含用于初始化和处理调度器的代码。

服务使用 Application_Start 方法初始化一个 Threading.Timer 对象,您可以修改 web.config(key="period") 以更改计时器回调之间的默认时间段,但目前默认时间段是 120000 毫秒。您可以设置的最小值是 30000 毫秒。

计时器回调(Timer_Handler 方法)是调度器检查是否有任何必须执行的任务的地方。此方法还会检查正在运行的任何任务是否已超出任务 AbortAfter 属性定义的允许执行时间。

SchedulerController.vb 是调度器的核心。此类包含 Web 服务公开的方法的实现,还包含管理计划任务的执行和取消的代码。

我只想评论以下方法

GetAvailableTasks,此方法将检查 Web 服务 bin 文件夹中的所有 DLL 和 EXE,并查找继承自 Task 基类的类。为此,我使用 Assembly 类和 Type 类的 BaseType 属性。如果您想更改任务完成后的行为方式(如果您调用了 RaiseTaskFinishedEvent 方法),请更改 SchedulerControllerTaskFinished 方法;如果您想更改抛出异常时发生的情况(如果您使用 Try/Catch 块并且正在使用 RaiseTaskExceptionEvent 方法),请更改调度器控制器中 TaskException 方法的代码。

SincronizeTaskObjectAndDataRow 方法负责同步数据集和 SchedulerController 的任务对象列表。

关注点

目前,计划任务列表以 XML 文件形式存储,因为我想提供一个不需要任何数据库的工具。但是,我更喜欢将任务列表存储在某个数据库中。

请记住,在如何安排任务方面还有很大的改进空间,因此请检查并比较 Windows 计划任务应用程序中的选项,以了解我的意思。在此示例中,没有身份验证或安全检查,因此我强烈建议您实施某种安全检查。您还必须实现的代码是从 UI 取消正在运行的任务。

历史

VB.NET 代码 V1.0

© . All rights reserved.