Workflow persisitence

 1 using System.Activities.DurableInstancing;
 2 using System.Threading;
 3 using System.Activities;
 4 namespace ConfiguringSqlPersistenceStore {
 5 class Program {
 6 static void Main(string[] args) {
 7 //setup sql persistence store
 8 string sqlPersistenceDBConnectionString=
 9 @"Data Source=.\sqlexpress;
10 Initial Catalog=PersistenceDatabase;
11 Integrated Security=True";
12 SqlWorkflowInstanceStore sqlWFInstanceStore =new SqlWorkflowInstanceStore(
13 sqlPersistenceDBConnectionString);
14 //create and run workflow application
15 AutoResetEvent waitHandler = new
16 AutoResetEvent(false);
17 WorkflowApplication wfApp =
18 new WorkflowApplication(new Workflow1());
19 wfApp.InstanceStore = sqlWFInstanceStore;
20 wfApp.Unloaded = (arg) => {
21 waitHandler.Set();
22 };
23 wfApp.PersistableIdle = (arg) => {
24 return PersistableIdleAction.Unload;
25 };
26 wfApp.Run();
27 waitHandler.WaitOne();
28 }
29 }
30 }

In the StartAndUnloadInstance method, we may want to use the following statement
to persist a workflow instance:

1 wfApp.PersistableIdle = (e) => {
2 return PersistableIdleAction.Persist;
3 };

Instead of return PersistableIdleAction.Unload;, the persisted workflow
will be locked by the instance owner, and the workflow will exit without unloading. The
consequence is, if we try to load a locked workflow instance from the database with a new
WorkflowApplication object, we will get the following exception:
Unhandled Exception: System.Runtime.DurableInstancing.InstanceLockedException: The
execution of an InstancePersistenceCommand was interrupted because the instance
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx' is locked by a different instance owner. This error
usually occurs because a different host has the instance loaded. The instance owner ID of
the owner or host with a lock on the instance is 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx'.
If we want to persist a workflow and unload the workflow from the memory, we should use
PersistableIdelAction.Unload instead of PersistableIdleAction.Persist.

 

If we are going to have multiple hosts potentially loading the same workflow instance, we need
to specify the instance store's DefaultInstanceOwner:

InstanceHandle handle = instanceStore.CreateInstanceHandle();
InstanceView view=instanceStore.Execute(handle,new CreateWorkflowOwnerCommand(),TimeSpan.FromSeconds(5));
handle.Free();
instanceStore.DefaultInstanceOwner = view.InstanceOwner;

This is the execution sequence of persistence-related events:

  •  PersistableIdle
  •  Idle
  •  Completed (optional)
  •  Unloaded (optional)

 

Microsoft Windows Workflow Foundation 4.0 Cookbook p182-189

 

BUT, In my application I found that Idle is called first, followed by PersistableIdle.

 

Key Code:

 

            DataRowView idstring = instancelistBox.SelectedItem as DataRowView;
            Guid id = new Guid(idstring["InstanceId"].ToString());
            instance.Load(id);

            //Run() First, then set Idle and PersistableIdle   
            instance.Run();
            instance.Idle = workflowIdel;
            instance.PersistableIdle = delegate (WorkflowApplicationIdleEventArgs ie)
            {
             return PersistableIdleAction.Unload;
             };

            instance.Unloaded = (ue) =>
            {            
              var deleteOwnerCmd = new DeleteWorkflowOwnerCommand();
                store.Execute(handle, deleteOwnerCmd, TimeSpan.FromSeconds(30));
                handle.Free();
            };

 

 

 

posted @ 2012-08-05 21:08  wyking  阅读(797)  评论(0编辑  收藏  举报