ASP.NET 工作流:支持长时间运行操作的 Web 应用程序
在线浏览代码
本文将介绍以下内容:
|
本文使用了以下技术: Windows Workflow Foundation、ASP.NET |
- 从上一个活动获取订单数据。这通常是通过数据绑定完成的,稍后您可以看到它的示例。
- 从数据库中查找与该订单关联的客户。
- 根据该客户的位置从数据库中查找税率。
- 使用税率和与订单关联的订单项目进行一些简单的数学运算。
- 将税金总额存储在与后续活动绑定的属性中以完成结账过程。
- 通过从 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 站点接受或拒绝该职位。
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 ...
随机推荐
- window自带的公式面板
如何使用Windows数学输入面板生成数学公式 数学输入面板是一个Windows自带的数学公式编辑软件,该软件最大的特点就是可以简单方便地写出数学公式.本文主要探讨该软件的一些基本用法. 工具/原料 ...
- python-day02-购物车
购物车 需求: 1.启动程序后,让用户输入工资,然后打印商品列表: 2.容许用户根据商品编号购买商品: 3.用户选择商品后,检测余额是否足够,够了就直接扣款,不够就提醒客户: 4.随时可以退出,退出时 ...
- windows下安装tomcat8
1.下载tomcat,下载地址:https://tomcat.apache.org/download-80.cgi 2.官网下载下来的tomcat是zip格式,解压到安装目录 3.修改环境变量: CA ...
- 微信小程序连接本地接口(转)
原文地址 最近的一个项目就是微信小程序 第一次接触微信开发者工具,并进行小程序的后端开发, 于是想看一下小程序如何请求本地的后台服务接口 wx.request({ url: 'http://local ...
- StanFord ML 笔记 第四部分
第四部分: 1.生成学习法 generate learning algorithm 2.高斯判别分析 Gaussian Discriminant Analysis 3.朴素贝叶斯 Navie Baye ...
- Python开发【模块】:Celery 分布式异步消息任务队列
Celery 前言: Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个 ...
- 21纯 CSS 创作文本滑动特效的 UI 界面
原文地址:https://segmentfault.com/a/1190000014842868 简化版地址:https://scrimba.com/c/cgaZLh6 感想:笨蛋,想不出自己的东西. ...
- JMeter做http接口功能测试
1. 普通的以key-value传参的get请求 e.g. 获取用户信息 添加http请求:填写服务器域名或IP:方法选GET:填写路径:添加参数:运行并查看结果. 2. 以Json串传参的post请 ...
- 【ASP.NET 问题】Win7中IIS被防火墙阻止导致外网无法访问的解决方法。
今天装了IIS7.0,把网站发布了上去,但局域网的其他电脑始终无法访问主机上的网站. 于是想到防火墙的原因,把防火墙关掉,可以正常访问,但是打开就不行. 于是去网上找资料,总算搞定了. 原来在防火墙的 ...
- ASP.NET Core MVC 概述
https://docs.microsoft.com/zh-cn/aspnet/core/mvc/overview?view=aspnetcore-2.2 ASP.NET Core MVC 概述 20 ...