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

在 ASP.NET 中使用工作流调度任务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (5投票s)

2011年6月23日

CPOL

4分钟阅读

viewsIcon

54576

downloadIcon

1627

在 ASP.NET 中调度任务的众多方法之一

引言

在本文中,我想演示一种调度任务的方法。在这种情况下,我将使用工作流基础的 ASP.NET 应用程序。但是,首选的实现方式是使用任务计划程序或 Windows 服务作为主要选项。

我遇到了这些文章,它们解释了在 ASP.NET 中实现调度程序的不同方法

调度作业的注意事项

当我们考虑调度作业的解决方案时,Windows 服务和 Windows 任务计划程序会浮现在脑海中。如果您有兴趣评估哪个更好,请查看以下博客

部署 - 对于任务计划程序和 Windows 计划程序,我们需要编写部署包/脚本。如果对任务有任何更改,我们需要更新所有运行服务或任务的服务器。

维护 - 每个计划作业通常会变成一个单独的应用程序(主要是控制台)。随着此类作业数量的增加,维护这些应用程序会变得很麻烦。但是,总有例外。此外,处理密码更改是任务计划程序的一个小问题。但是,如果您想自动化这一点,可以编写一些脚本。

控制 - 在任务计划程序中,将任务安排在几秒钟内运行可能是一个挑战。

安全 - 来自 MSDN 的注意事项:通过使用 caclsTasks 文件夹分配权限的用户将能够访问所有用户的计划任务。请谨慎选择授予 Tasks 文件夹访问权限的用户。

错误处理和通知 - 如果任务启动失败并出错,我们需要在每个作业中实现错误报告。

Using the Code

我们直接进入一些代码。

步骤 1:创建您的 ASP.NET 应用程序

我不会详细介绍第一步。如果您不熟悉 ASP.NET,可以参考 ASP.NET

打开 Visual Studio 2010,选择“新建项目”,选择“ASP.NET Web 应用程序”,输入项目名称,然后单击“确定”。

步骤 2:创建您选择的工作流应用程序

  1. 右键单击解决方案,选择“添加”->“新建项目…”
  2. 工作流 -> 工作流控制台应用程序

步骤 3:创建您的工作流,它应该有一个要执行的任务和一个在连续 while 循环中暂停/休眠的计时器。

  1. 您可以使用应用程序创建的默认工作流,也可以创建一个新的。
  2. 添加一个 While 活动,并将条件设置为 True
  3. While 活动中添加一个顺序活动。
  4. 将一个 Invoke 方法活动添加到顺序活动中
  5. 配置类和方法参数,方法应具有 Public Static 访问修饰符。
  6. Timer 添加到顺序活动中的 Invoke 方法活动之后。
  7. 将计时器设置为适当的间隔。

活动现在看起来应该像这样

workflow.JPG

上面工作流的 XAML 代码如下。

在本例中,我每隔 10 秒写入调试信息。您可以更改 InvokeMethod 活动以调用您各自的业务或服务组件中的适当方法。

 <Activity mc:Ignorable="sap" 
	x:Class="WorkflowConsoleApplication.WorkflowWithScheduler" 
          sap:VirtualizedContainerService.HintSize="526,702" 
          mva:VisualBasic.Settings="Assembly references and imported namespaces 
		for internal implementation" 
          xmlns="<a href="http://schemas.microsoft.com/netfx/2009/xaml/activities">
		http://schemas.microsoft.com/netfx/2009/xaml/activities</a>" 
          xmlns:local="clr-namespace:WorkflowConsoleApplication" 
          xmlns:mc="<a href="http://schemas.openxmlformats.org/markup-compatibility/2006">
		http://schemas.openxmlformats.org/markup-compatibility/2006</a>" 
          xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" 
          xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" 
          xmlns:s="clr-namespace:System;assembly=mscorlib" 
		xmlns:s1="clr-namespace:System;assembly=System" 
		xmlns:s2="clr-namespace:System;assembly=System.Xml" 
		xmlns:s3="clr-namespace:System;assembly=System.Core" 
		xmlns:sad="clr-namespace:System.Activities.Debugger;
		assembly=System.Activities" 
		xmlns:sap="<a href="http://schemas.microsoft.com/netfx/2009/
		xaml/activities/presentation">http://schemas.microsoft.com/
		netfx/2009/xaml/activities/presentation</a>" 
		xmlns:scg="clr-namespace:System.Collections.Generic;
		assembly=System" xmlns:scg1="clr-namespace:System.Collections.
		Generic;assembly=System.ServiceModel" 
		xmlns:scg2="clr-namespace:System.Collections.Generic;
		assembly=System.Core" xmlns:scg3="
		clr-namespace:System.Collections.Generic;assembly=mscorlib" 
		xmlns:sd="clr-namespace:System.Data;assembly=System.Data" 
		xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" 
		xmlns:st="clr-namespace:System.Text;assembly=mscorlib" 
		xmlns:x="<a href="http://schemas.microsoft.com/winfx/2006/xaml">
		http://schemas.microsoft.com/winfx/2006/xaml</a>">
  <Sequence sad:XamlDebuggerXmlReader.FileName="C:\Users\Chinna\documents\
	visual studio 2010\Projects\SchedulerSample\WorkflowConsoleApplication1\
	WorkflowWithScheduler.xaml" sap:VirtualizedContainerService.HintSize="486,657">
    <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
        <x:Boolean x:Key="IsExpanded">True</x:Boolean>
      </scg3:Dictionary>
    </sap:WorkflowViewStateService.ViewState>
    <While sap:VirtualizedContainerService.HintSize="464,533" Condition="True">
      <Sequence sap:VirtualizedContainerService.HintSize="438,417">
        <sap:WorkflowViewStateService.ViewState>
          <scg3:Dictionary x:TypeArguments="x:String, x:Object">
            <x:Boolean x:Key="IsExpanded">True</x:Boolean>
          </scg3:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <InvokeMethod sap:VirtualizedContainerService.HintSize="218,130" 
		MethodName="WriteDebug" TargetType="local:MyClass" />
        <WriteLine sap:VirtualizedContainerService.HintSize="218,61" Text="testing it..." />
        <Delay Duration="00:00:10" sap:VirtualizedContainerService.HintSize="218,22" />
      </Sequence>
    </While>
  </Sequence>
</Activity></span>

步骤 4:设置和启动工作流运行时

加载和启动工作流运行时在 Application_Start 事件中完成。

  1. 打开 Global.asax.cs 文件
  2. Application_Start 事件中,添加以下代码。我们将创建的 WorkflowRuntime 对象的引用添加到 Application 对象集合中。
System.Workflow.Runtime.WorkflowRuntime
workflowRuntime = new System.Workflow.Runtime.WorkflowRuntime();
System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService
manualService = new
System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService();
workflowRuntime.AddService(manualService);
workflowRuntime.StartRuntime();
Application["WorkflowRuntime"] =
workflowRuntime;

步骤 5:在 ASP.NET 应用程序启动时启动工作流。

遵循 Application_Start 事件中的上述代码,您可以启动工作流服务,如果它应该在应用程序启动时启动。在此代码中,我们正在创建一个类型为 WorkflowConsoleApplication1.Workflow1 的工作流实例并启动它。

步骤 6:在 ASP.NET 应用程序停止时停止工作流服务。

Application_End 事件中添加以下代码以停止工作流运行时。

System.Workflow.Runtime.WorkflowRuntime workflowRuntime = 
	Application["WorkflowRuntime"] as System.Workflow.Runtime.WorkflowRuntime;
workflowRuntime.StopRuntime();</span>

步骤 7:使用 ASP.NET 测试调度程序。
验证工作流是否已执行您期望的任务。

步骤 8:方便地启动/停止工作流
如果您不希望在 Application_Start 事件中启动工作流,则可以在其中一个网页上的按钮单击时执行此操作。应用程序的身份验证和授权可以提供对此的访问。

优点

  • 无需为调度程序单独部署包
  • WF 跟踪服务
  • 无需对调度程序进行额外配置或维护
  • 在工作进程的安全上下文中运行
  • 可以实现基于角色的访问,以允许控制工作流
  • 不需要服务器管理员干预

缺点

  • 这不是处理计划任务的传统方法
  • 由于关键的架构差异,在设计启用工作流的 ASP.NET 应用程序时应考虑托管基础结构。
  • 应用程序的设计应考虑到应用程序的可维护性。

历史

  • 2011年6月23日:初稿
© . All rights reserved.