Home > WF4

[WF4]Long Running WF4 Host

17. August 2010

In WF3, when a workflow is delayed and persisted in persistence store, after the timer expired, workflow will resume from database automatically.Now in WF4, we have to resume a persisted workflow manually, So can we create a long running WF4 that can monitor a delayed workflow and resume a workflow automatically after the delay timer expired. Here is a class that can achieve this:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Xml.Linq;

using System.Threading;

using System.Activities.DurableInstancing;

using System.Runtime.DurableInstancing;

using System.Activities;

using System.Configuration;

public class LongRunningWFHost{

    Activity workflow=null;

    ManualResetEvent waitHandler=new ManualResetEvent(false);

    static XName wfHostTypeName;

    bool completed = false;

    private static readonly XName WorkflowHostTypePropertyName =

        XNamespace.Get("urn:schemas-microsoft-com:System.Activities/4.0/properties").GetName("WorkflowHostType");

    SqlWorkflowInstanceStore instanceStore = null;

    InstanceHandle instanceHandle = null;

    public LongRunningWFHost(Activity workflow){

        this.workflow=workflow;

    }

 

    public void Run(){

        wfHostTypeName = XName.Get("Version" + Guid.NewGuid().ToString(), 
                                   typeof(WorkflowWithDelay).FullName);

        this.instanceStore = SetupSqlpersistenceStore();

        this.instanceHandle = 
            CreateInstanceStoreOwnerHandle(instanceStore, wfHostTypeName);

        WorkflowApplication wfApp = CreateWorkflowApp();

        wfApp.Run();

        while (true) {

            this.waitHandler.WaitOne();

            if (completed) {

                break;

            }

            WaitForRunnableInstance(this.instanceHandle);

            wfApp =CreateWorkflowApp();

            try {

                wfApp.LoadRunnableInstance();

                waitHandler.Reset();

                wfApp.Run();

            } catch (InstanceNotReadyException) {

                Console.WriteLine("Handled expected InstanceNotReadyException, retrying...");

            }

        }

        Console.WriteLine("workflow completed.");

    }

    public void WaitForRunnableInstance(InstanceHandle handle) {

        var events=instanceStore.WaitForEvents(handle, TimeSpan.MaxValue);

        bool foundRunnable = false;

        foreach (var persistenceEvent in events) {

            if (persistenceEvent.Equals(HasRunnableWorkflowEvent.Value)) {

                foundRunnable = true;

                break;

            }

        }

        if (!foundRunnable) {

            Console.WriteLine("no runnable instance");

        }

    }

    public WorkflowApplication CreateWorkflowApp() {

        WorkflowApplication wfApp = new WorkflowApplication(workflow);

        wfApp.InstanceStore = this.instanceStore;

        Dictionary<XName, object> wfScope = new Dictionary<XName, object>{

                { WorkflowHostTypePropertyName, wfHostTypeName }

        };

        wfApp.AddInitialInstanceValues(wfScope);

        wfApp.Unloaded = (e) => {

            Console.WriteLine("Unloaded");

            this.waitHandler.Set();

        };

        wfApp.Completed = (e)=>{

            this.completed=true;

        };

        wfApp.PersistableIdle = (e) => {

            return PersistableIdleAction.Unload;

        };

        wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs abortArgs) {

            Console.WriteLine("Workflow aborted (expected in this sample)");

        };

        return wfApp;

    }

    private SqlWorkflowInstanceStore SetupSqlpersistenceStore() {

        string connectionString =
            ConfigurationManager.AppSettings["SqlWF4PersistenceConnectionString"].ToString();

        SqlWorkflowInstanceStore sqlWFInstanceStore = new SqlWorkflowInstanceStore(connectionString);

        return sqlWFInstanceStore;

    }

    // Configure a Default Owner for the instance store so instances can be re-loaded from WorkflowApplication

    private static InstanceHandle CreateInstanceStoreOwnerHandle(InstanceStore store,
                                                                 XName wfHostTypeName) {

        InstanceHandle ownerHandle = store.CreateInstanceHandle();

        CreateWorkflowOwnerCommand ownerCommand = new CreateWorkflowOwnerCommand() {

            InstanceOwnerMetadata = {

                { WorkflowHostTypePropertyName, new InstanceValue(wfHostTypeName) }

            }

        };

        store.DefaultInstanceOwner = store.Execute(ownerHandle, ownerCommand,
                                                   TimeSpan.FromSeconds(30)).InstanceOwner;

        return ownerHandle;

    }

}

Source Code: CSWF4LongRunningHost.zip (60.11 kb)

WF4

Comments

11/17/2011 9:17:48 AM #
Thanks you so much for the great blog Smile
11/25/2011 6:18:46 PM #
Your help means a lot to use <a href="www.nffleece.com/north-face-fleece-jacketsw-c-2.html"><strong>womens north face denali</strong></a>.This is a really quality post <a href="www.nffleece.com/north-face-fleece-jacketsw-c-2.html"><strong>womens north face fleece</strong></a>. Nice information many thanks to the author.<a href="www.nffleece.com/north-face-fleece-jacketsw-c-2.html"><strong>north face womens fleece</strong></a>.
12/22/2011 8:02:30 PM #
<a href="...rthfacehonsale.org"><strong>north face outlet</strong></a> read this article after, <a href="...rthfacehonsale.org"><strong>cheap north face</strong> </a> have a  lot of new things is our reality didn't learn <a href="...rthfacehonsale.org"><strong>north face shop</strong></a>, the article is well written, <a href="www.northfacehonsale.org/index.php North Face Apex Bionic</strong></a> key points, concise content <a href="www.northfacehonsale.org/index.php North Face Apex Bionic</strong> </a>
http://www.northfacehonsale.org/
1/7/2012 12:47:22 AM #

555linli10
The main dangers in this life are the people who want to change everything --- or nothing.
1/16/2012 11:13:20 PM #
I visited your blog for the first time and became your fan. Keep posting as I am going to read it everyday.
supra shoes
supra shoes
1/21/2012 11:14:39 PM #
But why? How appear Roger Bannister could allegation out of his Oxford lab every day, batter about a harder &lt;strong&gt;www.e-suprashoes.com/.../strong&gt; in attenuate covering slippers, not alone accepting faster but never accepting hurt, and set a almanac afore lunch?

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading