{"id":26,"date":"2008-01-07T17:46:10","date_gmt":"2008-01-07T21:46:10","guid":{"rendered":"http:\/\/jianmingli.com\/wp\/?p=26"},"modified":"2008-01-17T11:09:23","modified_gmt":"2008-01-17T15:09:23","slug":"windows-workflow-foundation-wwf","status":"publish","type":"post","link":"https:\/\/jianmingli.com\/wp\/?p=26","title":{"rendered":"Windows Workflow Foundation (WWF)"},"content":{"rendered":"<p><strong>Requirement<\/strong><\/p>\n<ol>\n<li>Visual Studio 2005 Version 8.0.50727.42\u00a0<\/li>\n<li>.Net Framework 3.0 or above<\/li>\n<li>\n<p class=\"first-para\">Visual Studio extensions for <font onclick=\"nextHit('forward')\" class=\"b24-hit\">workflow<\/font> (file: Visual Studio 2005 Extensions for <font onclick=\"nextHit('forward')\" class=\"b24-hit\">Windows<\/font> <font onclick=\"nextHit('forward')\" class=\"b24-hit\">Workflow<\/font> <font onclick=\"nextHit('forward')\" class=\"b24-hit\">Foundation<\/font> (EN).exe): <a target=\"_top\" href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?familyid=5D61409E-1FA3-48CF-8023-E8F38E709BA6&amp;displaylang=en\" class=\"url\"><em class=\"emphasis\"><font color=\"#b85b5a\">http:\/\/www.microsoft.com\/downloads\/details.aspx?familyid=5D61409E-1FA3-48CF-8023-E8F38E709BA6&amp;displaylang=en<\/font><\/em><\/a><\/p>\n<\/li>\n<\/ol>\n<p><strong>Workflow\u00a0Types<\/strong><\/p>\n<ul>\n<li>Sequential workflow\n<ul>\n<li>Good for business process<\/li>\n<li>Not so good for user interaction<\/li>\n<\/ul>\n<\/li>\n<li>State machinen workflow\n<ul>\n<li>Good for lots of user interactions<\/li>\n<\/ul>\n<\/li>\n<li>Rule driven workflow, based on sequential workflow\n<ul>\n<li>More complicate and costly<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong><em>Two types of activities <\/em><\/strong><\/p>\n<ul>\n<li>Composite activities\n<ul>\n<li>Contains other activities, e.g. sequential acitivities<\/li>\n<\/ul>\n<\/li>\n<li>Basic activities\n<ul>\n<li>Does the actual work\u00a0<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong><em>System.Workflow.Runtime.WorkFlowRuntime object<\/em><\/strong><\/p>\n<ul>\n<li>Properties\n<ul>\n<li>IsStarted<\/li>\n<\/ul>\n<\/li>\n<li>Methods\n<ul>\n<li>AddService<\/li>\n<li>CreateWorkflow<\/li>\n<li>StartRuntime<\/li>\n<li>StopRuntime<\/li>\n<\/ul>\n<\/li>\n<li>Events\n<ul>\n<li>Started<\/li>\n<li>Stopped<\/li>\n<li>WorkflowCompleted<\/li>\n<li>WorkflowIdled<\/li>\n<li>WorkflowTerminated<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong><em>WorkflowInstance<\/em> object<\/strong><\/p>\n<ul>\n<li>Properties\n<ul>\n<li>InstanceId<\/li>\n<li>WorkflowRuntime<\/li>\n<\/ul>\n<\/li>\n<li>Methods\n<ul>\n<li>ApplyWorkflowChanges<\/li>\n<li>GetWorkflowDefinition<\/li>\n<li>Resume<\/li>\n<li>Start<\/li>\n<li>Suspend<\/li>\n<li>Terminate: <code lang=\"charp\">instance.Terminate(\"User cancellation.\");<\/code><\/li>\n<\/ul>\n<\/li>\n<li>Events<\/li>\n<li>Status:<code lang=\"csharp\"> workflowInstance.GetWorkflowDefinition().ExecutionStatus.ToString();<\/code><\/li>\n<\/ul>\n<p><strong><em>Activity<\/em> object<\/strong><\/p>\n<ul>\n<li>Properties\n<ul>\n<li>Description<\/li>\n<li>Enabled<\/li>\n<li>ExecutionResult<\/li>\n<li>ExecutionStatus<\/li>\n<li>ActivityExecutionStatus<\/li>\n<li>Name<\/li>\n<li>Parent<\/li>\n<li>WorkflowInstanceId<\/li>\n<\/ul>\n<\/li>\n<li>Methods (they are all <em>protected virtual<\/em> methods)\n<ul>\n<li>Cancel<\/li>\n<li>Clone<\/li>\n<li>Execute<\/li>\n<li>GetActivityByName<\/li>\n<li>Load<\/li>\n<li>RaiseEvent<\/li>\n<li>RaiseGenericEvent&lt;T&gt;<\/li>\n<li>Save<\/li>\n<\/ul>\n<\/li>\n<li>Events\u00a0<\/li>\n<\/ul>\n<p><strong><em>ActivityExecutionContext<\/em> class<\/strong><\/p>\n<ul>\n<li>Created by workflow runtime<\/li>\n<li>Provide info about workflow instance\n<ul>\n<li>Initialization<\/li>\n<li>Timers<\/li>\n<li>General execution flow<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Sequence Activity Object<\/strong><\/p>\n<ul>\n<li>Is a composite\u00a0activity\u00a0<\/li>\n<\/ul>\n<p><strong>Code Activity<\/strong><\/p>\n<p><strong>Throw\/FaultHandler Activities<\/strong><\/p>\n<ul>\n<li>Each FaultHandler is designed to handle one, and only one, exception type.<\/li>\n<\/ul>\n<p><strong>Suspend Activity<\/strong><\/p>\n<p><strong>Terminate Activity<\/strong><\/p>\n<ul>\n<li>Difference from workflow termination by unhandled exception\n<ul>\n<li>WorkflowTerminatedEventArgs.Exception is of the type <em>System.Workflow. ComponentModel.WorkflowTerminatedException<\/em><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Workflow interprocess communication<\/strong><\/p>\n<ul>\n<li>WF uses an abstraction layer to buffer workflow from host\n<ul>\n<li>Local communication service<\/li>\n<li>Need to add ExternalDataService to workflow runtime?<\/li>\n<\/ul>\n<\/li>\n<li>Create a workflow data communicaiton\u00a0interface<\/li>\n<li>Annotate with <em>[ExternalDataExchange]<\/em> (marker interface for local communication service)<br \/>\n<code lang=\"cshpar\"><br \/>\npublic interface IMVDataService<br \/>\n{<br \/>\n[ExternalDataExchange]<br \/>\nvoid MVDataUpdate (DataSet mvData);<br \/>\n}<\/code><\/li>\n<li>Create a workflow data event argument class<br \/>\n<code lang=\"csharp\"><br \/>\n[Serializable]<br \/>\npublic class MVDataAvailableArgs : ExternalDataEventArgs<br \/>\n{<br \/>\npublic MVDataAvailableArgs(Guid instanceId)<br \/>\n: base(instanceId)<br \/>\n{<br \/>\n}<br \/>\n}<br \/>\n<\/code><\/li>\n<\/ul>\n<p><strong>Pluggable services<\/strong><\/p>\n<ul>\n<li>Additonal software functions that your workflow can use to complete their tasks<\/li>\n<li>Some are optional and some are required<\/li>\n<li>They are pluggable<\/li>\n<li>Base workflow services\n<ul>\n<li>WorkflowPersistenceService<\/li>\n<li>WorkflowQueuingService<\/li>\n<li>WorkflowRuntimeService<\/li>\n<li>WorkflowSchedulerService\n<ul>\n<li>DefaultWorkflowSchedulerService<\/li>\n<li>ManualWorkflowSchedulerService<\/li>\n<\/ul>\n<\/li>\n<li>WorkflowSubscriptionService<\/li>\n<li>WorkflowTransactionService<\/li>\n<li>TrackingService\n<ul>\n<li>SqlTrackingService\n<ul>\n<li>Can use Workflowmonitor to query<\/li>\n<li>Tracking specification objects<\/li>\n<li>Tracking retrieval objects\n<ul>\n<li>Example\u00a0\n<ul>\n<li>SqlTrackingQuery<\/li>\n<\/ul>\n<\/li>\n<li>Activity events\n<ul>\n<li>ActivityTrackingPoint<\/li>\n<li>ActivityTrackingLocation<\/li>\n<\/ul>\n<\/li>\n<li>Workflow events<\/li>\n<li>User events<\/li>\n<\/ul>\n<\/li>\n<li>Tracking records are decorated with annotations<\/li>\n<li>Tracking level determined in tracking profile\n<ul>\n<li>XML doc<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>ConsoleTrackingService<\/li>\n<li>SimpleFileTrackingService<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Pass Dictionary object as a parameter to workflow instance<\/strong><\/p>\n<ul>\n<li>In the activity class<br \/>\n<code lang=\"csharp\"><br \/>\npublic sealed partial class Workflow1: SequentialWorkflowActivity<br \/>\n{<br \/>\nprivate Int32 _delay = 10;public Workflow1()<br \/>\n{<br \/>\nInitializeComponent();<br \/>\n}\/\/ Receives value from parameter<br \/>\npublic Int32 Delay<br \/>\n{<br \/>\nget { return _delay; }<br \/>\nset<br \/>\n{<br \/>\nif (value &lt; 0 || value &gt; 120)<br \/>\n{<br \/>\nvalue = 10;<br \/>\n}<br \/>\nif (ExecutionStatus == ActivityExecutionStatus.Initialized)<br \/>\n{<br \/>\n_delay = value;<br \/>\ndelayActivity1.TimeoutDuration = new TimeSpan(0, 0, _delay);<br \/>\n}<br \/>\n}<br \/>\n}private void PreDelayMessage(object sender, EventArgs e)<br \/>\n{<br \/>\nMessageBox.Show(\"Pre-delay code is being executed.\");<br \/>\n}private void PostDelayMessage(object sender, EventArgs e)<br \/>\n{<br \/>\nMessageBox.Show(\"Post-delay code is being executed.\");<br \/>\n}<br \/>\n}<\/code><\/li>\n<li>In the main program<br \/>\n<code lang=\"csharp\"><br \/>\nclass Program<br \/>\n{<br \/>\nprivate static AutoResetEvent _waitHandle = new AutoResetEvent(false);<br \/>\nstatic void Main(string[] args)<br \/>\n{<br \/>\nWorkflowRuntime wfr = WorkflowFactory.GetWorkflowRuntime();<br \/>\nwfr.WorkflowIdled +=<br \/>\nnew EventHandler<workfloweventargs><\/workfloweventargs>(wfr_WorkflowIdled);<br \/>\nwfr.WorkflowCompleted +=<br \/>\nnew EventHandler<workflowcompletedeventargs><\/workflowcompletedeventargs>(wfr_WorkflowCompleted);<br \/>\nwfr.WorkflowTerminated +=<br \/>\nnew EventHandler<workflowterminatedeventargs><\/workflowterminatedeventargs>(wfr_WorkflowTerminated);Int32 delay = 0;<br \/>\nstring val = args.Length &gt; 0 ? args[0] : \"10\";<br \/>\nif (!Int32.TryParse(val, out delay))<br \/>\n{<br \/>\nConsole.WriteLine(\"You must pass in an integer value.\");<br \/>\nreturn;<br \/>\n}\/\/ Constructs a Dictionary object as workflow instance parameter<br \/>\nDictionary<string,><\/string,> prms = new Dictionary<string,><\/string,>();<br \/>\nprms.Add(\"Delay\", delay);Console.WriteLine(\"Waiting for workflow completion ({0} seconds).\", val);WorkflowInstance wfi =<br \/>\n\/\/ Pass the Dictionary object as parameter<br \/>\nwfr.CreateWorkflow(typeof(LongRunningWorkflow.Workflow1), prms);<br \/>\nwfi.Start();<br \/>\n_waitHandle.WaitOne();<br \/>\nConsole.WriteLine(\"Done.\");<br \/>\n}<br \/>\nstatic void wfr_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)<br \/>\n{<br \/>\nConsole.WriteLine(\"Workflow terminated.\");<br \/>\n_waitHandle.Set();<br \/>\n}<br \/>\nstatic void wfr_WorkflowIdled(object sender, WorkflowEventArgs e)<br \/>\n{<br \/>\nConsole.WriteLine(\"Workflow idled.\");<br \/>\n}static void wfr_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)<br \/>\n{<br \/>\nConsole.WriteLine(\"Workflow completed.\");<br \/>\n_waitHandle.Set();<br \/>\n}<br \/>\n}<\/code><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Requirement Visual Studio 2005 Version 8.0.50727.42\u00a0 .Net Framework 3.0 or above Visual Studio extensions for workflow (file: Visual Studio 2005 Extensions for Windows Workflow Foundation (EN).exe): http:\/\/www.microsoft.com\/downloads\/details.aspx?familyid=5D61409E-1FA3-48CF-8023-E8F38E709BA6&amp;displaylang=en Workflow\u00a0Types Sequential workflow Good for business process Not so good for user interaction &hellip; <a href=\"https:\/\/jianmingli.com\/wp\/?p=26\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[8],"tags":[],"class_list":["post-26","post","type-post","status-publish","format-standard","hentry","category-dotnet"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8cRUO-q","_links":{"self":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/26","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=26"}],"version-history":[{"count":0,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/26\/revisions"}],"wp:attachment":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=26"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=26"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=26"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}