ASP.NET 工作流:支持长时间运行操作的 Web 应用程序
在线浏览代码
本文将介绍以下内容:
|
本文使用了以下技术: Windows Workflow Foundation、ASP.NET |
![](http://i.msdn.microsoft.com/zh-cn/3685e341-a040-4937-8d6c-1e273aa8dced.fig01_L(zh-cn).gif)
- 从上一个活动获取订单数据。这通常是通过数据绑定完成的,稍后您可以看到它的示例。
- 从数据库中查找与该订单关联的客户。
- 根据该客户的位置从数据库中查找税率。
- 使用税率和与订单关联的订单项目进行一些简单的数学运算。
- 将税金总额存储在与后续活动绑定的属性中以完成结账过程。
- 通过从 Execute 方法返回“完成”状态标记向工作流运行时通知该活动已完成。
public class PasswordOperation : Operation {
Status ChangePassword(Guid userId, string pw) {
// Create a web service proxy:
UserService svc = new UserService();
// This can take up to 20 sec for
// the web server to respond:
bool result = svc.ChangePassword( userId, pw );
Logger.AccountAction( "User {0} changed pw ({1}).",
userId, result);
return Status.Completed;
}
}
public class PasswordOperation : Operation {
Status ChangePasswordImproved(Guid userId, string pw) {
// Create a web service proxy:
UserService svc = new UserService();
svc.ChangePasswordComplete += svc_ChangeComplete;
svc.ChangePasswordAsync( userId, pw );
return Status.Executing;
}
void svc_ChangeComplete(object sender, PasswordArgs e) {
Logger.AccountAction( "User {0} changed pw ({1}).",
e.UserID, e.Result );
Scheduler.SignalCompleted( this );
}
}
class MyActivity : Activity {
override ActivityExecutionStatus
Execute(ActivityExecutionContext ctx) {
// Do work here.
return ActivityExecutionStatus.Closed;
}
}
- 创建一个派生自 Activity 的类。
- 覆盖 Execute 方法。
- 创建一个工作流队列,用于接收所等待的异步事件已完成的通知。
- 订阅该队列的 QueueItemAvailable 事件。
- 启动长时间运行操作(例如发送电子邮件请经理审核工作岗位的申请)。
- 等待外部事件发生。这样可以有效地发出该活动已变为空闲的信号。可通过返回 ExecutionActivityStatus.Executing 向工作流运行时指出此情况。
- 事件发生时,处理 QueueItemAvailable 事件的方法会从队列中删除该项,然后将其转换为期望的数据类型并处理结果。
- 通常这样会终止活动的操作。然后工作流运行时通过返回 ActivityExecutionContext.CloseActivity 发出信号。
void AddService(object service)
C:\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN\
SqlWorkflowPersistenceService sqlSvc =
new SqlWorkflowPersistenceService(
@"server=.;database=WF_Persist;trusted_connection=true",
true, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
wfRuntime.AddService(sqlSvc);
- 求职者访问 Trey Research Web 站点并表示对某个工作岗位感兴趣。
- 向经理发送电子邮件通知有新的申请人。
- 该经理将审核申请并批准求职者得到某个特定的职位。
- 向该求职者发送电子邮件告知所提议职位的相关信息。
- 求职者会访问该 Web 站点接受或拒绝该职位。
![](http://i.msdn.microsoft.com/zh-cn/3685e341-a040-4937-8d6c-1e273aa8dced.fig03(zh-cn).gif)
public abstract class AsyncActivity : Activity {
private string queueName;
protected AsyncActivity(string queueName) {
this.queueName = queueName;
}
protected WorkflowQueue GetQueue(
ActivityExecutionContext ctx) {
var svc = ctx.GetService<WorkflowQueuingService>();
if (!svc.Exists(queueName))
return svc.CreateWorkflowQueue(queueName, false);
return svc.GetWorkflowQueue(queueName);
}
protected void SubscribeToItemAvailable(
ActivityExecutionContext ctx) {
GetQueue(ctx).QueueItemAvailable += queueItemAvailable;
}
private void queueItemAvailable(
object sender, QueueEventArgs e) {
ActivityExecutionContext ctx =
(ActivityExecutionContext)sender;
try { OnQueueItemAvailable(ctx); }
finally { ctx.CloseActivity(); }
}
protected abstract void OnQueueItemAvailable(
ActivityExecutionContext ctx);
}
- 开始长时间运行操作并调用 SubscribeToItemAvailable。
- 通知工作流运行时该活动处于空闲状态。
- 工作流实例通过持久性服务序列化为数据库。
- 操作结束时,将某个项目发送到工作流队列中。
- 这将触发工作流实例从数据库中还原。
- 抽象模板方法 OnQueueItemAvailable 由基类 AsyncActivity 执行。
- 该活动完成其操作。
public partial class AssignJobActivity : AsyncActivity {
public const string QUEUE NAME = "AssignJobQueue";
public AssignJobActivity()
: base(QUEUE_NAME)
{
InitializeComponent();
}
protected override ActivityExecutionStatus Execute(
ActivityExecutionContext ctx) {
// Runs before idle period:
SubscribeToItemAvailable(ctx);
return ActivityExecutionStatus.Executing;
}
protected override void OnQueueItemAvailable(
ActivityExecutionContext ctx) {
// Runs after idle period:
Job job = (Job)GetQueue(ctx).Dequeue();
// Assign job to employee, save in DB.
Employee employee = Database.FindEmployee(this.WorkflowInstanceId);
employee.Job = job.JobTitle;
employee.Salary = job.Salary;
}
}
protected void LinkButtonJoin_Click(
object sender, EventArgs e) {
WorkflowInstance wfInst =
Global.WorkflowRuntime.CreateWorkflow(typeof(MainWorkflow));
wfInst.Start();
Response.Redirect(
"GatherEmployeeData.aspx?id=" + wfInst.InstanceId);
}
public class AssignJobPage : System.Web.UI.Page {
/* Some details omitted */
void ButtonSubmit_Click(object sender, EventArgs e) {
Guid id = QueryStringData.GetWorkflowId();
WorkflowInstance wfInst = Global.WorkflowRuntime.GetWorkflow(id);
Job job = new Job();
job.JobTitle = DropDownListJob.SelectedValue;
job.Salary = Convert.ToDouble(TextBoxSalary.Text);
wfInst.EnqueueItem(AssignJobActivity.QUEUE_NAME, job, null, null);
buttonSubmit.Enabled = false;
LabelMessage.Text = "Email sent to new recruit.";
}
}
WorkflowInstance wfInst =
Global.WorkflowRuntime.GetWorkflow(id);
public class Global : HttpApplication {
public static WorkflowRuntime WorkflowRuntime { get; set; }
protected void Application_Start(object sender, EventArgs e) {
WorkflowRuntime = new WorkflowRuntime();
InstallPersistenceService();
WorkflowRuntime.StartRuntime();
// ...
}
protected void Application_End(object sender, EventArgs e) {
WorkflowRuntime.StopRuntime();
WorkflowRuntime.Dispose();
}
void InstallPersistenceService() {
// Code from listing 4.
}
}
ASP.NET 工作流:支持长时间运行操作的 Web 应用程序的更多相关文章
- [ASP.NET Core 3框架揭秘] 服务承载系统[1]: 承载长时间运行的服务[上篇]
借助.NET Core提供的承载(Hosting)系统,我们可以将任意一个或者多个长时间运行(Long-Running)的服务寄宿或者承载于托管进程中.ASP.NET Core应用仅仅是该承载系统的一 ...
- 三点经验:长时间运行函数需要随时发射信号报告进度,以及设置bool变量随时可以退出,每做一步操作必须及时记录和处理相关信息
三点经验:长时间运行函数需要随时发射信号报告进度,以及设置bool变量随时可以退出,每做一步操作必须及时记录和处理相关信息 不能到最后一起处理,否则万一中间出错了,这个记录状态就全部都乱了.
- 定时器解决js长时间运行脚本问题
一般地,单个js操作的运行时间不应超过100毫秒,否则的话,会影响用户体验,用户会认为自己与界面失去联系.而对于一些复杂的任务,可能无法在100ms内完成,甚至会突破浏览器限制(调用栈大小限制和长时间 ...
- WPF窗口长时间无人操作鼠标自动隐藏
在软件开发中有时会有等待一段时间无人操作后隐藏鼠标,可能原因大致如下: 1.为了安全性,特别是那些需要用到用户名和密码登录服务端的程序,常常考虑长期无人操作,程序自动跳转到用户登录界面: 2.软件为了 ...
- WinForm触摸屏程序功能界面长时间不操作自动关闭回到主界面 z
操作者经常会在执行了某操作后,没有返还主界面就结束了操作然后离开了,程序应该关闭功能窗体自动回到主界面方便下一位操作者操作.那么对于WinForm程序怎么实现呢? 实现原理:拦截Application ...
- WPF程序长时间无人操作
在软件开发中为了安全性,特别是那些需要用到用户名和密码登录服务端的程序,常常考虑长期无人操作,程序自动跳转到用户登录界面. 判断程序是否长时间无人操作,有两个依据,第一个是鼠标长时间不动,第二个是鼠标 ...
- Web页面长时间无操作后再获取焦点时转到登录界面
今天开始讲新浪博客搬到博客园. 在工作中遇到的小问题,感觉有点意思,就记录下来吧! 该问题分为两种情况,一.Web页面长时间无操作后,在对其进行操作,比如点击“首页”.“设 ...
- iOS开发笔记--如何实现程序长时间未操作退出
我们使用金融软件经常会发现手机锁屏或者长时间未操作就会退出程序或者需要重新输入密码等情况.下面让我们看一下如何实现这种功能.我们知道iOS有一个事件循环机制,也就是大家所说的runloop.我们在对程 ...
- WPF:鼠标长时间无操作,窗口隐藏
//设置鼠标长时间无操作计时器 private System.Timers.Timer MouseTimerTick = new System.Timers.Timer(10000); private ...
随机推荐
- Service Worker初体验
http://web.jobbole.com/84792/ http://imweb.io/topic/56592b8a823633e31839fc01
- Android之socket多线程
一.添加权限 <uses-permission android:name="android.permission.INTERNET" /> 二.输入输出流 客户端和服务 ...
- navicat创建存储过程的小问题
再简单的东西长时间不用了就会出错,特此即时的记录下来,以便以后参考! 转自:http://blog.csdn.net/winy_lm/article/details/49690633 以下为navic ...
- Getting Physical With Memory.CPU如何操作内存
原文标题:Getting Physical With Memory 原文地址:http://duartes.org/gustavo/blog/ [注:本人水平有限,只好挑一些国外高手的精彩文章翻译一下 ...
- python函数的return
return语句用于退出函数,向调用方返回一个表达式.return在不带参数的情况下(或者没有写return语句),默认返回None.None是一个特殊的值,它的数据类型是NoneType.NoneT ...
- error while obtaining ui hierarchy xml file...用 uiautomatorviewer 获取安卓手机软件页面时报错
Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn't ...
- C# ORM修改实体层
实体层:[数据库中是么以偶Contents2这个字段的],之所以在实体层添加一个Contents2,是因为: 所以在添加之后: 返回json形式,就用Contents,后台添加就用Contents2. ...
- Linux中使用python测试主机存活 Linux系统CentOS Linux release 7.3.1611 (Core) py版本Python 2.7.5
下面是最初的情况 #/usr/bin/env python # -*- coding: utf-8 -*- import os import time import subprocess import ...
- Enterprise Library
https://msdn.microsoft.com/en-us/library/ff648951.aspx
- jq check 复选变单选。
$("input[type='checkbox']").on("click",function(e){ var $checked = $("input ...