博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

工作流服务Workflow Service(2):SendActivity

Posted on 2009-01-17 12:35  生鱼片  阅读(2261)  评论(1编辑  收藏  举报

无状态的工作流服务每次调用服务都会创建一个新的工作流实例。无状态的服务在客户端和服务器端不需要上下文交换。而有状态的则需要,
在下面的例子中我们开发一个有状态的工作流服务,我们使用WSHttpContextBinding。

1.首先定义IAddStatefulService接口,代码如下:

namespace CaryWFLib
{
    [ServiceContract]
    public interface IAddStatefulService
    {
        [OperationContract]
        void StartWorkflow();

        [OperationContract]
        Double Add(Double num1, Double num2);       

        [OperationContract]
        void StopWorkflow();
    }
}

2.然后我们设计我们的工作流,我们这次使用状态机工作流,如下图:

 wfwcf1

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,如下图:
wfwcf2 

我们还是像使用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 的通道。