无状态的工作流服务每次调用服务都会创建一个新的工作流实例。无状态的服务在客户端和服务器端不需要上下文交换。而有状态的则需要,
在下面的例子中我们开发一个有状态的工作流服务,我们使用WSHttpContextBinding。
1.首先定义IAddStatefulService接口,代码如下:
namespace CaryWFLib { [ServiceContract] public interface IAddStatefulService { [OperationContract] void StartWorkflow(); [OperationContract] Double Add(Double num1, Double num2); [OperationContract] void StopWorkflow(); } }
2.然后我们设计我们的工作流,我们这次使用状态机工作流,如下图:
ReceiveActivity的使用可以参考工作流服务Workflow Service(1):ReceiveActivity这篇文章。
3.我们在IIS中宿主该工作流服务,完成后可以使用如下代码进行测试。
namespace AddStatefulServiceConsole { class Program { static void Main(string[] args) { AddStatefulServiceClient client1 = new AddStatefulServiceClient(); AddStatefulServiceClient client2 = new AddStatefulServiceClient(); Console.WriteLine("Server endpoint: {0}",client1.Endpoint.Address.ToString()); client1.StartWorkflow(); client2.StartWorkflow(); double result; result = client1.Add(1, 2); Console.WriteLine("Client1 计算的结果为: {0}", result); result = client2.Add(1,2); Console.WriteLine("Client2 计算的结果为: {0}", result); client1.StopWorkflow(); client1.Close(); client2.StopWorkflow(); client2.Close(); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } } }
4.除了使用上面的方法来调用工作流服务,我们还可是使用WF本身提供的SendActivity来调用工作流服务,我们新建一个顺序工作流控制
台项目。在工作流设计器中我们拖入SendActivity,如下图:
我们还是像使用ReceiveActivity同样的方式来设置SendActivity的ServiceOperationInfo属性,ChannelToken是每一个SendActivity必须要正确的
设置属性,通道令牌用来指定通道名称、通道范围和用于建立通道的终结点配置名称。Name属性为AddChannel,EndpointName属性为AddEndpoint,
该属性与App.config中的相对应,还有OwnerActivityName属性为SendWorkflow。OwnerActivityName和Nam属性决定WCF使用的通信通道,
我们的例子中所有的SendActivity的ChannelToken都是同样的设置,保证所有的服务操作都使用相同的通道,当相同的通道被使用,服务消息将会
在同一个工作流服务实例交换。
App.config如下:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <wsHttpContextBinding> <binding name="AddBindingConfig" openTimeout="00:00:30" sendTimeout="00:00:30" receiveTimeout="00:00:30" closeTimeout="00:00:30" > </binding> </wsHttpContextBinding> </bindings> <client> <endpoint address="http://localhost/CaryWFWCF/AddStatefulServiceWorkflow.svc" binding="WSHttpContextBinding" bindingConfiguration="AddBindingConfig" contract="CaryWFLib.IAddStatefulService" name="AddEndpoint"> </endpoint> </client> </system.serviceModel> </configuration>
5.测试程序如下:
namespace WorkflowConsoleSend { class Program { static void Main(string[] args) { using (WorkflowRuntime workflowRuntime = new WorkflowRuntime()) { AutoResetEvent waitHandle = new AutoResetEvent(false); workflowRuntime.WorkflowCompleted += delegate( object sender, WorkflowCompletedEventArgs e) { Console.WriteLine("result is {0}", e.OutputParameters["Result"]); waitHandle.Set(); }; workflowRuntime.WorkflowTerminated += delegate( object sender, WorkflowTerminatedEventArgs e) { Console.WriteLine(e.Exception.Message); waitHandle.Set(); }; //create channel manager service in order to manage and //reuse WCF channels. workflowRuntime.AddService(new ChannelManagerService()); Dictionary<String, Object> parameters = new Dictionary<string, object>(); parameters.Add("Num1", 1); parameters.Add("Num2", 2); WorkflowInstance instance = workflowRuntime.CreateWorkflow( typeof(WorkflowConsoleSend.SendWorkflow), parameters); instance.Start(); waitHandle.WaitOne(); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } } } }
ChannelManagerService 负责根据在活动 ChannelToken 中定义的通道令牌,创建 SendActivity 的通道。