微软工作流基础知识.doc_第1页
微软工作流基础知识.doc_第2页
微软工作流基础知识.doc_第3页
微软工作流基础知识.doc_第4页
微软工作流基础知识.doc_第5页
已阅读5页,还剩544页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

WorkFlow从入门到精通目录第一章 WF简介1第二章 workflow运行时8第三章 workflow实例22第四章 活动及workflow类型介绍38第五章 workflow跟踪51第六章 加载和卸载实例82第七章 基本活动的操作105第八章 调用外部方法及工作流132第九章 逻辑流活动177第十章 事件活动213第十一章 并行活动260第十二章 策略和规则295第十三章 打造自定义活动338第十四章 基于状态的工作流388第十五章 工作流和事务413第十六章 明式工作流450第十七章 关联及本地主机通信476第一章 WF简介学习完本章,你将掌握:1.了解工作流的概念和理论2.把WF和BizTalk与WCF做比较3.开始使用WF进行编程4.知道怎样使用Visual Studio工作流支持 以下是一小段进行邮政编码验证的代码 /mailto:stringUSCode=(d5$)|(d5$-d4$/);/mailto:stringCanadianCode=ABCEGHJKLMNPRSTVXYDA-ZdA-Zd/;publicstaticboolValidatePostalCode(stringstr)return(Regex.IsMatch(str,USCode)|Regex.IsMatch(str,CanadianCode);这没有什么特别的:“测试一个输入的字符串,如果为美国ZIP编码或者加拿大邮政编码则返回True,否则返回False”。这是一段很实用的代码,事实上假如你不想在ASP.NET中使用其它验证控件的话,你就可在你的ASP.NET中使用这段验证逻辑。我们现在就创建一个Workflow应用程序,它将进行同样的验证,并且返回验证是否通过的信息。 创建一个基于控制台的Workflow项目1.启动Visual Studio 20082.创建顺序工作流控制台应用程序项目3.项目名称中输入PCodeFlow4.点击确定,将自动生成下面的初始界面在编辑代码或插入Workflow项前,停留片刻看看Workflow项目为你生成的两个文件:Program.cs:从许多方面可以看出,这是一个典型的控制台应用程序源文件。然而,这个模板增加了大量代码来支持Workflow的操作。理解这些代码是本书的一个主要目标,但本章只是简单了解一下它做了些什么。Workflow1.cs:这是一个Workflow组件,我们将对其进行修改以进行邮政编码的验证,第一次使用你就可以放入许多东西,但我们现在还是从使用这个简单的Workflow开始工作吧。创建一个工作流在工具箱中拖一个IfElse活动组件到workflow设计界面上。我们现在将使用IfElse活动组件来问下面的问题:“我们已有的一个字符串是一个合法的邮政编码吗?”。我们在代码中将确实使用先前你看到的代码段中的正则表达式来问这一问题。但在我们进行这一步前请仔细看看workflow的视图设计器。workflow视图设计器提醒我们没有提供相应的代码来做这一决定。假如你看看命名为“ifElseBranchActivity1”的左边分支的右上角,你将看到里面有一个惊叹号标记的小圆形图标。这是workflow视图设计器在告诉你workflow并不完整。假如你试图编译带有这种提醒图标的项目时,将会编译报错。如你把鼠标移到图标上并单击呈现出的向下箭头时,你还能看到更多关于这一错误情况的信息。在IfElse活动的分支上添加代码1.移动鼠标到命名为“ifElseBranchActivity1”的左边分支上,单击以在属性面板上激活这一分支的属性。2.我们添加一个条件,意思是说workflow执行到分支时将强制其执行一些动作(条件判断为True时,将执行左边分支)。为做到这些,单击“condition”属性激活条件类型属性的下拉列表。从列表中你可以选择“代码条件”类型、“(无)”类型和“声明性规则条件”类型。这里选择“代码条件”类型。3.上述步骤完成后,“condition”类型属性用户界面会包含一个“+”号,我们单击展开它的子属性,该子属性也命名为“condition”,单击以激活它。4.“condition”属性需要输入我们想添加的内部事件名字。当条件需要判断时这个事件将激发。在本例子中我们输入“EvaluatePostalCode”。Visual studio 2008在幕后为你在workflow源文件中添加了你在“condition”属性中所指明的事件。稍候我们将添加在事件激发时所要执行的正则表达式代码段。在我们做这些工作之前,让我们继续在workflow视图设计器上工作,我们刚刚增加了一个条件,它将引发工作流选择左边路径还是右边路径。但是两条路径中都没有指明工作流将进行的动作。我们在左边“ifElseBranchActivity1”分支和右边“ifElseBranchActivity2”分支中添加活动。添加Code活动1.拖一个“Code”活动到workflow视图设计器上,并放到左边分支(ifElseBranchActivity1)的区域内。2.就像先前添加条件判断的代码一样,我们将为该分支添加被选中时执行的代码。单击“codeActivity1”图标以在属性面板中激活它的属性。3.在“ExecuteCode”属性中输入“PostalCodeValid”。Visual Studio 2008会自动插入该事件。稍候我们会提供对应的执行代码。右边分支也同样做,只是要在“ExecuteCode”属性中输入“PostalCodeInValid”。在我们的workflow中添加事件处理代码1.打开Workflow.cs准备进行编辑2.添加引用:using System.Text.RegularExpression;3.定位到“EvaluatePostalCode”方法上,插入下面的代码:private void EvaluatePostalCode(object sender, ConditionalEventArgs e)string USCode = (d5$)|(d5$-d4$);string CanadianCode = ABCEGHJKLMNPRSTVXYDA-ZdA-Zd; e.Result = (Regex.IsMatch(_code, USCode) | Regex.IsMatch(_code, CanadianCode);变量e是“ConditionalEventArgs”类型的实例,它用来告知“IfElse”活动应选择哪条路径。4.我们也需要为workflow活动添加一种能力,以便接受输入的字符串来进行验证工作。为此我们添加下面的代码,我们将声明一个名为“PostalCode”的公有属性。private string _code=string.Empty;public string PostalCode get return _code; set _code = value; 有了这些,我们的workflow应用程序就可以进行编译了,但程序并不完整,我们还要在Workflow1.cs文件中定位到“PostalCodeValid”方法并插入下面的代码:Console.Write(The postal code 0 is valid., _code);同样在“PostalCodeInValid”方法中插入下面的代码:Console.Write(The postal code 0 is *invalid*., _code);调用工作流1.打开Program.cs文件。2.定位到:WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(PCodeFlow.Workflow1),wfArgs);3.把上述代码替换为:DictionarywfArgs=newDictionary();wfArgs.Add(PostalCode,args.Length0?args0:); WorkflowInstanceinstance=workflowRuntime.CreateWorkflow(typeof(PCodeFlow.Workflow1),wfArgs);编译应用程序执行你的工作流应用程序1.打开命令提示符窗口。2.在命令提示符下定位到编译后所生成的应用程序目录。3.输入pcodeflow 12345查看执行结果。4.输入pcodeflow 1234x再看看执行结果。第二章 workflow运行时学习完本章后,你将掌握:1.在你的应用程序中使用workflow2.理解“WorkflowRuntime”对象的的基本功能3.知道如何启动和停止workflow运行时4.能够使用各种workflow运行时的相关事件当你在WF环境中执行任务时,需要一些东西来监管执行的过程,这个东西就是命名为“WorkflowRuntime”的对象。WorkflowRuntime启动一个独立的工作流任务。在你的任务执行过程中,WorkflowRuntime也会针对不同的情况响应对应的事件。并且,WorkflowRuntime还能在你的执行环境中增加一个附加的服务来保持跟踪。WF架构纵览见下图:WF和你的应用程序并行执行。其实,我们需要你的应用程序作为宿主。宿主应用程序可以是Windows Forms应用程序,控制台应用程序,ASP.NET WEB应用程序,甚至可以是一个Windows Server。WF运行时和你的应用程序同在一个.NET应用程序域执行,每个应用程序域只有一个唯一的WorkflowRuntime实例,试图在一个应用程序域中建立第二个WorkflowRuntime的实例的话,其结果就是抛出一个“InvalidOperationException”异常。workflow应用程序-“workflows”-意思指创建的逻辑上的一组活动。这些逻辑上的活动用来完成你需要的工作流任务。当你宿主workflow运行时的时候,其实你就在操作工作流中的活动并让workflow运行时执行他们。其结果就是生成一个workflow实例,workflow实例是一个当前正执行的workflow任务,它能自己完成逻辑上的一组活动,回忆第一章吧,活动能执行你提供的代码并且能对输入的数据做出相应的决定。下一章我们将简述工作流实例,后面几章将对活动进行介绍。在宿主应用程序中添加WF一、创建一个名称为WorkflowHost的控制台应用程序项目二、为项目添加名为System.Workflow.Runtime的引用三、宿主workflow运行时1.打开Program.cs文件准备编辑2.在“using System.Text;”下添加以下代码:“using System.Workflow.Runtime”3.定位到“Main”方法,在里面添加以下代码:WorkflowRuntime workflowRuntime=new WorkflowRuntime();4.编译程序确认没有错误。在本章我们都将使用这一应用程序。四、深入了解WorkflowRuntime对象我们现在已经在我们的宿主应用程序中建立了一个WorkflowRuntime类型的实例,该是简单的了解怎样和这个对象交互的时候了。和大多数有用的对象一样,WorkflowRuntime也暴露了一些方法和属性,我们可用他们来控制Workflow运行时的环境。表2-1列出了所有WorkflowRuntime属性,表2-2则列出了我们经常使用的方法。 表2-1 WorkflowRuntime的属性属性功能IsStarted用来指明workflow运行时是否已经启动并准备接受workflow实例。当宿主调用“StartRuntime”前IsStarted为False。期间它一直维持True直到宿主调用“StopRuntime”为止。需注意的是当它正在运行中你不能增加核心服务。Name获取或设置和WorkflowRuntime关联的名字。Workflow运行时正在运行中你不能设置这个属性(也就是说当IsStarted为True)。企图这样做的结果就是抛出一个“InvalidOperationException”异常。表2-2 WorkflowRuntime的方法 方法功能方法功能AddService为workflow运行时添加指定的服务。能添加的服务类型和时间受到种种限制。关于服务的详细信息将在第五章介绍。CreateWorkflow创建一个workflow实例,它包含一些指定(但可选)的参数。假如workflow运行时没有启动,该方法就调用StartRuntime方法。GetWorkflow通过指明workflow实例的标识符(由一个Guid组成)来检索workflow实例。假如这个workflow实例是空闲和持久化保存的,它将被重新加载并执行。StartRuntime启动workflow运行时和相关服务,并引发“Started”事件。StopRuntime停止workflow运行时和相关服务,并引发“Stoped”事件。还有更多的关于WorkflowRuntime的方法,但表2-2中列出的方法是最经常用到的方法,也是我们将重点关注的方法。在workflow运行期间,WorkflowRuntime也将在各种时间引发许多事件,但我们将在后面的章节中介绍。创建一个Workflow运行时工厂单例和工厂设计模式的组合是强大的,因为工厂能保证只创建出一个曾创建的对象的单一实例,这正好符合我们的要求(在这里使用单例模式的原因主要是从效率上考虑,其次一个应用程序域也只能只有一个WorkflowRuntime),因为WorkflowRuntime完全有可能在不同的应用当中加载和启动(例如独立的应用模块)。让我们看看怎样创建一个WorkflowRuntime工厂。一、在项目中添加一个类型为类的新项,文件名为WorkflowFactory.cs。二、在WorkflowFactory.cs源文件中添加如下的引用using System.Workflow.Runtime;三、在类中添加下面的代码: /workflow runtime的单一实例private static WorkflowRuntime _workflowRuntime = null;private static object _syncRoot = new object();四、在上述代码后添加如下方法:/工厂方法public static WorkflowRuntime GetWorkflowRuntime()/多线程环境下防止并发访问lock (_syncRoot)if (null = _workflowRuntime)_workflowRuntime = new WorkflowRuntime();return _workflowRuntime;五、为类加上Public关键字,为防止类被直接实例化,还必须为类加上static标记,如下所示:public static class workflowFactory启动workflow运行时参考表2-2,里面有一个StartRuntime方法,从我们的工厂对象中调用这个方法很有意义,外部对象要求workflow运行时对象无需处理或担心运行时环境状态的初始化。我们需要在我们的应用程序通过这一步来建立我们需要的workflow环境。外部调用对象也需要workflow运行时对象易于使用。并不是一定要调用StartRuntime。假如我们建立了一个workflow实例,StartRuntime实际上就已被调用。假如我们曾经创建了一个workflow实例,或许并不用担心需要明确的调用StartRuntime。但是,一旦我们添加服务时,明确地调用它就很有必要,因为可增强代码的可维护性并确信运行时环境的状态已建立,这样任何人就都能使用workflow运行时对象。因此让我们在我们的工厂对象中做些轻微的更改并直接调用StartRuntime。1.打开WorkflowFactory.cs文件并定位到下面的代码上:_workflowRuntime = new WorkflowRuntime();2.在上面的代码下添加以下的代码:_workflowRuntime.Starttime();停止workflow运行时是否有办法启动一个workflow运行时很有意义,如何停止一个workflow运行时也一样。看看表2-2吧,里面有一个StopRuntime方法正好符合我们要求。调用StopRuntime方法会卸载所有正执行的workflow和服务并关闭workflow运行时环境。当然,正确调用StopRuntime位置是在你申请停止逻辑结束之前或者应用程序域关闭前调用。1.打开WorkflowFactory.cs文件并定位到下面的代码上_workflowRuntime = new WorkflowRuntime();2.在上面代码的前面增加以下代码:_workflowRuntime.Starttime();3.在WorkflowFactory.cs中增加StopWorkflowRuntime事件处理函数:static void StopWorkflowRuntime(object sender, EventArgs e)if (_workflowRuntime != null)if (_workflowRuntime.IsStarted)try_workflowRuntime.StopRuntime();catch (ObjectDisposedException)以下是WorkflowFactory.cs文件的完整源代码,在第五章之前我们不会做更多的改变:using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Workflow.Runtime;namespace WorkflowHostpublic static class WorkflowFactory/workflow runtime的单一实例private static WorkflowRuntime _workflowRuntime = null;private static object _syncRoot = new object();/工厂方法public static WorkflowRuntime GetWorkflowRuntime()/多线程环境下防止并发访问lock (_syncRoot)if (null = _workflowRuntime)AppDomain.CurrentDomain.ProcessExit += new EventHandler(StopWorkflowRuntime);AppDomain.CurrentDomain.DomainUnload += new EventHandler(StopWorkflowRuntime);_workflowRuntime = new WorkflowRuntime();_workflowRuntime.StartRuntime();return _workflowRuntime;static void StopWorkflowRuntime(object sender, EventArgs e)if (_workflowRuntime != null)if (_workflowRuntime.IsStarted)try_workflowRuntime.StopRuntime();catch (ObjectDisposedException)现在我们有了一个workflow运行时的创建工厂,然后我们将修改我们的主程序来使用它。使用workflow运行时创建工厂1.打开Program.cs文件并定位到如下代码上:WorkflowRuntime workflowRuntime=new WorkflowRuntime();2.把上面的代码修改成以下代码:WorkflowRuntime workflowRuntime=WorkflowFactory.GetWorkflowRuntime();表2-3 workflow运行时的相关事件描述事件功能Started当workflow运行时启动后激发。Stopped当workflow运行时停止后激发。WorkflowCompleted当一个workflow实例完成后激发。WorkflowIdled当一个workflow实例进入空闲状态时激发。当workflow实例进入了空闲状态后,你就有机会把他们从内存中卸载掉、存储到数据库并可在稍后的时间把它们加载进内存。WorkflowTerminated当一个workflow实例被终止后激发。在宿主中调用一个workflow实例的Terminate方法、或通过一个Terminate活动、或当workflow运行时产生一个未经捕获的异常时都会终止该workflow。 我们还将在第四章和第五章介绍更多的事件。在我们为上面的事件添加相应的事件处理程序时,你会看到生成的代码和上一章我们创建的基于工作台的顺序工作流应用程序中的代码完全一样(或几乎完全一样)。为了看看这些事件的作用,我们需要停止应用程序主线程一段时间。因此,我们使用一个基于内核的自动重置事件。一会儿后,我们将写出一些代码来使用上述事件中的几个,你需要不时看看第一章中PCodeFlow项目中的Program.cs文件,对比它们的不同以及该写入什么样的代码。尽管它们并不完全相同,但你在两个程序中还是能找到相同的内容。处理workflow运行时事件1.启动Visual Studio,打开项目的Program.cs源文件,定位到下面的代码上:WorkflowRuntime workflowRuntiem=WorkflowFactory.GetWorkflowRuntime();2.假如你用过.NET的委托,下面的代码你将非常熟悉。我们需要为我们感兴趣的事件增加相应的事件处理程序。我们现在就来为workflow空闲时和完成后增加相应的事件处理程序。稍候我们还会增加我们所需要的更多的事件处理程序。记住,下面的代码在步骤1定位的代码的下面:workflowRuntime.WorkflowIdled += new EventHandler(workflowIdled);3.下面的代码添加了对workflow完成后的事件处理:workflowRuntime.WorkflowCompleted += new EventHandler(workflowCompleted);4.现在添加对workflow终止后的事件处理:workflowRuntime.WorkflowTerminated += new EventHandler(workflowTerminated);5.假如你编译并运行WorkflowHost(本项目),这个应用程序能通过编译并运行。但没有执行workflow,因为我们并未告知workflow运行时去启动一个workflow实例(我们将在下章添加)。为以后做准备,我们还要添加一些代码。首先,为了激发workflow中的事件(以便我们观察它们),我们需要停止主线程足够长的时间,因此我们还将添加自动重置事件。在步骤3、4的代码下添加以下代码。Console.WriteLine(对待workflow完成。);waitHandle.WaitOne();Console.WriteLine(完成.);6.在Main方法前定义一个名为waitHandle的静态成员:private static AutoResetEvent waitHandle = new AutoResetEvent(false);7.添加名称空间:using System.Threading;8.由Vistual Studio 2008创建的上面三个事件对应的事件处理程序内都包含“throw new NotImplementedException();”。我们需要移除这些代码并定位到workflowIdled的事件处理程序内,写入下面的代码:Console.WriteLine(workflow实例空闲中);9.定位到workflowCompleted的事件处理程序内,写入下面的代码:Console.WriteLine(workflow实例已完成);waitHandle.Set();10.定位到workflowTerminated的事件处理程序内,写入下面的代码:Console.WriteLine(workflow实例已终止,原因:0。,e.Exception.Message);waitHandle.Set();完整的代码见列表2-2。列表2-2 WorkflowHost应用程序的完整代码using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Workflow.Runtime;using System.Threading;namespace WorkflowHostclass Programprivate static AutoResetEvent waitHandle = new AutoResetEvent(false);static void Main(string args)WorkflowRuntime workflowRuntime = WorkflowFactory.GetWorkflowRuntime();workflowRuntime.WorkflowIdled += new EventHandler(workflowRuntime_WorkflowIdled);workflowRuntime.WorkflowCompleted += new EventHandler(workflowRuntime_WorkflowCompleted);workflowRuntime.WorkflowTerminated += new EventHandler(workflowRuntime_WorkflowTerminated);Console.WriteLine(等待workflow完成。);waitHandle.WaitOne();Console.WriteLine(完成.);static void workflowRuntime_WorkflowIdled(object sender, WorkflowEventArgs e)Console.WriteLine(workflow实例空闲中);static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)Console.WriteLine(workflow实例已完成);waitHandle.Set();static void workflowRuntime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)Console.WriteLine(workflow实例已终止,原因:0。,e.Exception.Message);waitHandle.Set();下一章我们将深入workflow实例,假如现在你执行这个程序,他会一直挂起。为什么呢?因为我们从未执行一个workflow实例,因此我们加入的事件的从未被激发,也就未执行对应的事件处理程序。程序将永远挂起(或者你亲自终止它)。在下一章中当我们添加一个workflow实例并执行它时我们还会看到这个程序。第三章 workflow实例一个workflow实例由一个或多个活动组成。(我们将在第七章开始介绍各种活动:“Basic Activity Operations.”)“primary activity”或者“root activity”被称作“workflow definition”。“workflow definition”通常的行为是为其它将要工作的活动充当一个容器。 学习完本章,你将掌握:1.使用不带参数和带参数二种方式初始化一个workflow实例2.测定你运行中的workflow实例的状况3.停止workflow实例4.确定你的workflow空闲或终止的原因 一个workflow实例由一个或多个活动组成。(我们将在第七章开始介绍各种活动:“Basic Activity Operations.”)“primary activity”或者“root activity”被称作“workflow definition”。“workflow definition”通常的行为是为其它将要工作的活动充当一个容器。注:“workflow definition”是你要求workflow去执行的东西,而一个workflow实例是一个正在执行的“workflow definition”。它们之间有明显的区别,一个正在执行当中,而另一个则不是。workflow实例从哪里来?它们当然应由你来创建。如你有困难来完成这个任务,并且自动创建的workflow符合你的应用要求的话,也可由软件来完成,但至少你也要写出workflow的任务或者workflow运行时将为你执行的任务。Microsoft提供了workflow运行时,你还得创建余下的东西。毕竟,这是你的应用。WF在上述这些地方的创建上可以为你提供帮助,WF不仅将执行你创建的workflow实例,而且也将帮助你去创建它们。WF集成了丰富的图形界面设计器,它能帮你以相同的方式把workflow集成到你创建的ASP.NET Web Forms、Windows Forms或者WPF应用中。你可在工具箱上滚动鼠标,从许多活动项中选中一个,然后把它拖到设计界面上并释放它。假如这个活动项具有可配置的属性,你还可使用Visual Studio中的属性面板来配置它,使它符合你的意图。我们已在第一章简要地使用过workflow设计器,在这里我们将再次使用它,毕竟与WF相关的工作几乎全是创建workflow任务,workflow可视化设计器的使用是开发过程中巨大的一个组成部分。 workflow实例和任何其它软件类似。它们会开始执行、运行,直到遇到终止条件时终止。这些或许是数据库中的所有记录已被处理,所有需被压缩的档案已被压缩,或者workflow发向各个审批方的文档已被批复(同意或不同意),或者是处理已经完成。它只有一个正常的启动位置,但有一个或多个正常的可能停止的位置。实例也能维持错误、异常。你可以处理这些异常也可不处理它。在某些情况下,或许你不想去处理出现的异常,并留到以后进行处理。有时,一个workflow处理过程会执行很长很长时间才能完成。例如,一个处理过程发送了一份零件的订单并等待订单被接收。在workflow终止前须确认零件的型号和数目,而这或许会花去几天,几周甚至几月。因此,难道一个workflow实例也需要在内存里维持激活状态几天,几周或者几月吗?假如服务器崩溃或电源断电怎么办?你的workflow实例、数据、应用程序状态不是通通丢失了吗?workflow实例和组成实例的活动是workflow处理过程中的重要部分。WF已经为workflow实例的创建及执行提供了强大的支持。我们就来看看WorkflowInstance对象。 WorkflowInstance对象介绍workflowInstance是一个WF对象,它为你提供了你的独立的workflow任务上下文(环境)。你可使用这个对象去找到在你的处理任务中事情将是如何进行的。就像我们有方法和属性去控制workflow运行时一样,我们也有方法和属性并用它们和我们的workflow实例进行交互。表3-1列出了大多数WorkflowInstance属性,表3-2列出了经常使用的方法。我们还将在第五章看到一些额外的属性和方法,“工作流跟踪”。表3-1 WorkflowInstance的属性 属性功能InstanceId得到workflow实例的唯一标识(一个Guid)WorkflowRuntime得到本workflow实例的WorkflowRuntime表3-2 WorkflowInstance的方法 方法功能ApplyWorkflowChanges通过WorkflowChanges对象申请对workflow实例进行更改。这允许你在workflow执行时修改它(增加、移出或更改活动),当动态的更改实施时,workflow实例会被暂停。GetWorkflowDefinition检索本workflow实例的根(root)活动。Resume恢复执行先前被暂停的workflow实例。假如workflow实例并未处于暂停状态,则不做任何事情。假如workflow实例处在暂停状态,workflow运行时就会在workflow实例刚被恢复后触发WorkflowResumed事件。Start启动一个workflow实例的执行,在这个workflow实例根活动上调用ExecuteActivity。假如Start发生异常,它通过调用Terminate终止这个workflow实例,并附加异常相关信息作为终止的原因。Suspend同步暂停本workflow实例。假如workflow实例本就处于暂停状态,则不做任何事情。假如workflow实例正在运行,则workflow运行时就暂停该实例,然后设置SuspendOrTerminateInfoProperty(说明原因)并进入Suspend,触发WorkflowSuspended事件。Terminate同步终止本workflow实例。当宿主需要终止workflow实例时,workflow运行时就终止这个实例并试图持久化实例的最终状态。然后WorkflowInstance设置SuspendOrTerminateInfoProperty(说明原因)并进入Terminate。最后,它触发WorkflowTerminated事件并把终止原因传到WorkflowTerminateException中的Message属性并包含到WorkflowTerminatedEventArgs事件参数中。另外,假如在持久化时发生异常,workflow运行时取而代之地就把异常传到WorkflowTerminatedEventArgs事件参数中。还有更多和WorkflowInstance相关的方法还未列出。到第六章“实例的加载和卸载”,我们持久化工作流到数据库中时将看到他们的更多细节。 启动一个工作流实例当我们启动一个workflow实例前,我们必须有一个workflow任务让WF去执行。在第一章,我们通过Visual Studio为我们创建了一个基于workflow的项目,它自动包含一个workflow任务,我们对它进行了修改以进行U.S.和加拿大邮政编码的验证。如果需要的话,我们可以返回到那个项目去复制源代码,或者引用PCodeFlow.exe程序集。然后我们就可直接使用这个已创建的workflow。实际上,你可以这么去做。然而,我们还是应该试着去学会写workflow的应用。让我们通过使用一个包含延时的顺序工作流去模拟一个长时间运行的任务吧。我们将在延时前执行一些代码,以弹出一个信息对话框。在经过延时后,我们将再次弹出一个信息对话框来指明我们的工作已经结束。通过本书的学习过程,我们的例子将会越来越详细和丰富,但现在我们还处于入门阶段,我们还将保持我们的例子并把注意力更多的放到概念上而不是提高技巧上。注:记住,顺序工作流执行活动时一个接着一个。这个处理方式可和状态机工作流做下比较,状态机工作流执行活动时是基于状态的转变。假如你现在对此一片茫然的话,不用担心,我们将在下章进入该主题。在WorkflowHost解决方案中添加一个顺序工作流项目1.启动Visual Studio 2008,加载上一章创建的名为“WorkflowHost”的解决方案准备进行编辑。2.在解决方案中添加一个崭新的workflow项目。3.项目模板选择顺序工作流库。4.项目名称起名为:LongRunningWorkflow。现在打开workflow的视图设计器准备创建我们的workflow任务。在视图设计器中的大图片中,我们将添加三个活动到这个新workflow任务中:两个Code活动和一个Delay活动。Delay活动将被放到两个Code活动中间,目的是可让我们在Delay执行前和执行后都将弹出一个信息对话框。最初我们会指定一个合适的延时时间值,但稍后我们将对workflow任务进行修改,以使workflow任务初始化时能接受我们专门指定的一个延时时间值。 创建这个模拟需执行很长时间的顺序工作流1.激活workflow视图设计器,移动鼠标到工具箱中。2.从工具箱中选择Code活动,并把该组件拖拽到workflow设计器的表面。3.释放鼠标并让Code活动组件落到该顺序工作流中。4.就像在第一章一样,我们将添加一些代码到Code活动中以使worflow任务经过这个活动时执行。在此单击Code活动以确保该活动的属性面板已被激活。5.在属性面板中激活ExecuteCode属性的下拉编辑框,它将允许你命名将被触发的事件,该事件在Code活动中的代码执行时触发。6.输入“PreDelayMessage”。这样就添加了一个事件到worflow代码中。稍候,我们将修改这段代码以显示一个信息对话框。但现在我们仍继续在workflow的视图设计器上工作,因为我们需要添加另外两个活动。7.从工具箱中选择Delay活动并添加到Code活动的下面。注:顺序活动,就像我们现在所做的工作一样,是以顺序的方式执行活动。顺序由workflow视图设计器中活动的位置决定。在workflow设计器窗口的顶部的活动首先执行,对于其它活动的执行顺序则按到视图设计器窗口底部的走向(箭头)决定。在下章我们还将重温这一过程。8.我们需要为我们的Delay活动建立一个延时时间值

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论