工作流学习过程-持久化服务

工作流系统中有很大一部分需要和人进行交互,有的时候需要很长的时间,所以我们不可能让工作流实例一直保存在内存当中,这就需要进行持久化操作。
工作流的持久化就是保存工作流的某些状态信息到持久化存储里,比如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; }
}
}

 

转载于:https://www.cnblogs.com/gotolovo/archive/2010/10/29/1864288.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值