惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The GitHub Blog
The GitHub Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
Y
Y Combinator Blog
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
M
MIT News - Artificial intelligence
博客园 - Franky
V
Visual Studio Blog
I
InfoQ
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
博客园 - 司徒正美
L
LangChain Blog

博客园 - gotolovo

导出csv 导出excel 正则学习电话匹配 logmanager des 加密 解密 - gotolovo c# 发送邮件 工作流学习过程-事务 工作流学习过程-状态机 蛋疼的viewstate 工作流学习过程-使用关联 工作流学习过程-本地服务之事件处理 工作流学习过程-本地服务之调用方法 工作流学习过程-验证活动 工作流学习过程-自定义活动 工作流学习过程-开篇 基本的几个排序算法 关于sql中时间的格式转换 数据行变列 请编程遍历页面上所有TextBox控件并给它赋值为空
工作流学习过程-持久化服务
gotolovo · 2010-10-29 · via 博客园 - gotolovo

工作流系统中有很大一部分需要和人进行交互,有的时候需要很长的时间,所以我们不可能让工作流实例一直保存在内存当中,这就需要进行持久化操作。
工作流的持久化就是保存工作流的某些状态信息到持久化存储里,比如sql数据库,文件中,一旦被保存到持久化存储里了,工作流就可以从内存中移除掉,在需要的时候在进行装载。

持久化服务是WF中核心服务之一,WF框架提供一个标准的持久化服务SqlWorkflowPersistenceService,利用它可以将工作流状态信息存放在Sql Server数据库中,
你也可以自己实现持久化服务,你必须继承自WorkflowPersistenceService这个类,自定义的持久化服务可以把数据存储在二进制文件,xml,其他关系型数据库中等等,
但是一个工作流实例一次只能使用一个持久化服务。

一旦你将持久化服务加载到工作流引擎中,你就不需要手动去干涉了,他会自动的完成相应的操作。在以下状态的时候,工作流会被持久化。

1. idle的时候(如等待外部事件,使用DelayActivity)。

2. 工作流完成或终止。

3. 当TransactionScopeActivity完成的时候。

4. 当CompensatableSequenceActivity完成的时候。

5. 当一个装饰有PersistOnCloseAttribute的自定义活动完成的时候。

6. 当你手动的去调用Unload或TryUnload方法的时候。

如果你使用DelayActivity的时候,持久化服务也会存储DelayActivity的过期时间,并且持久化服务会定期检查是否过期,以准备从新恢复工作流状态,
SqlWorkflowPersistenceService有一个LoadingInterval属性可以设置获取加载间隔的长度。

有的时候当工作流变成idle的时候,你也可以选择不进行持久化存储,这种情况适合当你等待的外部事件比较频繁,而且事件很快就被接收的时候,
因为这个时候如果你在进行持久化存储,你花在卸载和装载上时间会更多,还不如不进行持久化存储呢。

下面我们完成一个例子来说如何使用SqlWorkflowPersistenceService:

1.首先我们需要建立我们的持久化数据库,WF已提供了响应sql脚本,位置如下:

[WindowsFolder]\Microsoft.Net\Framework\v3.0\Windows Workflow Foundation\SQL\[language].[windows]这里面有SqlPersistenceService_Schema.sql
和SqlPersistenceService_Logic.sql两个文件用来生成持久化数据库.

创建好的持久化数据库里包含两张表, InstanceState和 CompletedScope,InstanceState表中记录未完成事例的运行状态,CompletedScope表记录当工做流使用事务的支持。

public partial class Persistencecs : Form
{
private WorkflowRuntimeManager workflowManager;
private WorkflowPersistenceService persistence;
private PersistenceService persistenceService;
private Dictionary<Guid, Workflow> workflows = new Dictionary<Guid, Workflow>();
private Workflow selectedWorkflow;
public Persistencecs()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
workflowManager
= new WorkflowRuntimeManager(new WorkflowRuntime());
AddServices(workflowManager.WorkflowRuntime);

workflowManager.WorkflowRuntime.WorkflowCreated

+= new EventHandler<WorkflowEventArgs>(WorkflowRuntime_WorkflowCreated);
workflowManager.WorkflowRuntime.WorkflowCompleted
+= new EventHandler<WorkflowCompletedEventArgs>(WorkflowRuntime_WorkflowCompleted);
workflowManager.WorkflowRuntime.WorkflowPersisted
+= new EventHandler<WorkflowEventArgs>(WorkflowRuntime_WorkflowPersisted);
workflowManager.WorkflowRuntime.WorkflowUnloaded
+= new EventHandler<WorkflowEventArgs>(WorkflowRuntime_WorkflowUnloaded);
workflowManager.WorkflowRuntime.WorkflowLoaded
+= new EventHandler<WorkflowEventArgs>(WorkflowRuntime_WorkflowLoaded);
workflowManager.WorkflowRuntime.WorkflowIdled
+= new EventHandler<WorkflowEventArgs>(WorkflowRuntime_WorkflowIdled);//initially disable these buttons until a workflow
//is selected in the data grid view
btnContinue.Enabled = false;
btnStop.Enabled
= false;//start the runtime prior to checking for any
//existing workflows that have been persisted
workflowManager.WorkflowRuntime.StartRuntime();//load information about any workflows that
//have been persisted
RetrieveExistingWorkflows();
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
//cleanup the workflow runtime
if (workflowManager != null)
{
workflowManager.Dispose();
}
}
void WorkflowRuntime_WorkflowCreated(object sender,WorkflowEventArgs e)
{
UpdateDisplay(e.WorkflowInstance.InstanceId,
"Created");
}
void WorkflowRuntime_WorkflowIdled(object sender,WorkflowEventArgs e)
{
UpdateDisplay(e.WorkflowInstance.InstanceId,
"Idled");
}
void WorkflowRuntime_WorkflowLoaded(object sender,WorkflowEventArgs e)
{
UpdateDisplay(e.WorkflowInstance.InstanceId,
"Loaded");
}
void WorkflowRuntime_WorkflowUnloaded(object sender,WorkflowEventArgs e)
{
UpdateDisplay(e.WorkflowInstance.InstanceId,
"Unloaded");
}
void WorkflowRuntime_WorkflowPersisted(object sender,WorkflowEventArgs e)
{
UpdateDisplay(e.WorkflowInstance.InstanceId,
"Persisted");
}
void WorkflowRuntime_WorkflowCompleted(object sender,WorkflowCompletedEventArgs e)
{
UpdateCompletedWorkflow(e.WorkflowInstance.InstanceId);
UpdateDisplay(e.WorkflowInstance.InstanceId,
"Completed");
}
private void RetrieveExistingWorkflows()
{
workflows.Clear();
//retrieve a list of workflows that have been persisted
foreach (SqlPersistenceWorkflowInstanceDescription workflowDesc in ((SqlWorkflowPersistenceService)persistence).GetAllWorkflows())
{
Workflow workflow
= new Workflow();
workflow.InstanceId
= workflowDesc.WorkflowInstanceId;
workflow.StatusMessage
= "Unloaded";
workflows.Add(workflow.InstanceId, workflow);
}
if (workflows.Count > 0)
{
RefreshData();
}
}
private void AddServices(WorkflowRuntime workflowRuntime)
{
String connStringPersistence
= String.Format("Initial Catalog={0};Data Source={1};Integrated Security={2};", "c6ps", @".", "SSPI");
persistence
= new SqlWorkflowPersistenceService(connStringPersistence, true, new TimeSpan(0, 2, 0), new TimeSpan(0, 0, 5));
workflowRuntime.AddService(persistence);
//add the external data exchange service to the runtime
ExternalDataExchangeService exchangeService = new ExternalDataExchangeService();
workflowRuntime.AddService(exchangeService);
//add our local service
persistenceService = new PersistenceService();
exchangeService.AddService(persistenceService);
}
private delegate void UpdateDelegate();/// <summary>
/// Update the status message for a workflow
/// </summary>
/// <param name="instanceId"></param>
/// <param name="statusMessage"></param>
private void UpdateDisplay(Guid instanceId, String statusMessage)
{
UpdateDelegate theDelegate
= delegate()
{
Workflow workflow
= GetWorkflow(instanceId);
workflow.StatusMessage
= statusMessage;
RefreshData();
//slow things down so you can see the status changes
System.Threading.Thread.Sleep(1000);
};
//execute the anonymous delegate on the UI thread
this.Invoke(theDelegate);
}
private Workflow GetWorkflow(Guid instanceId)
{
Workflow result
= null;
if (workflows.ContainsKey(instanceId))
{
result
= workflows[instanceId];
}
else
{
//create a new instance
result = new Workflow();
result.InstanceId
= instanceId;
workflows.Add(result.InstanceId, result);
}
return result;
}
private void RefreshData()
{
//setup binding for DataGridView
BindingSource source = new BindingSource();
dataGridView1.DataSource
= source;
source.DataSource
= workflows.Values;

dataGridView1.Columns[

0].MinimumWidth = 220;
dataGridView1.Columns[
1].MinimumWidth = 80;
dataGridView1.Columns[
2].MinimumWidth = 30;

dataGridView1.Refresh();
}

private void UpdateCompletedWorkflow(Guid instanceId)
{
UpdateDelegate theDelegate
= delegate()
{
Workflow workflow
= GetWorkflow(instanceId);
workflow.IsCompleted
= true;
};
//execute the anonymous delegate on the UI thread
this.Invoke(theDelegate);
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
//save the selected workflow instance
if (dataGridView1.SelectedRows.Count > 0)
{
DataGridViewRow selectedRow
= dataGridView1.SelectedRows[0];
selectedWorkflow
= selectedRow.DataBoundItem as Workflow;
SetButtonState();
}
}
private void SetButtonState()
{
if (selectedWorkflow != null)
{
btnContinue.Enabled
= !(selectedWorkflow.IsCompleted);
btnStop.Enabled
= !(selectedWorkflow.IsCompleted);
}
else
{
btnContinue.Enabled
= false;
btnStop.Enabled
= false;
}
}
#region 按钮事件处理
private void btnCreate_Click(object sender, EventArgs e)
{
workflowManager.StartWorkflow(
typeof(PersistenceWorkflow), null);
}
private void btnContinue_Click(object sender, EventArgs e)
{
if (selectedWorkflow != null)
{
persistenceService.OnContinueReceived(
new ExternalDataEventArgs(selectedWorkflow.InstanceId));
}
}
private void btnStop_Click(object sender, EventArgs e)
{
if (selectedWorkflow != null)
{
persistenceService.OnStopReceived(
new ExternalDataEventArgs(selectedWorkflow.InstanceId));
}
}
#endregion
}
public class Workflow
{
private Guid instanceId = Guid.Empty;
private String statusMessage = String.Empty;
private Boolean isCompleted;public Guid InstanceId
{
get { return instanceId; }
set { instanceId = value; }
}
public String StatusMessage
{
get { return statusMessage; }
set { statusMessage = value; }
}
public Boolean IsCompleted
{
get { return isCompleted; }
set { isCompleted = value; }
}
}