从WCF服务调用WF工作流

时间:2012-03-20 23:08:51

标签: wcf workflow-foundation-4

我有一个明确定义的服务合同,它暴露了一堆方法。我们有一个这个合同的典型服务实现,它与我们的MVC App一起托管在IIS 7中。

该体系结构是一个典型的分布式应用程序,其接口在基本核心库(可重新分发)中定义,独立服务库中的实现,最后是MVC App暴露实现的终点(在服务图书馆内。)

现在的情况是,这些现有服务方法之一需要执行一个逻辑过程,执行最多可能需要10分钟。在正常情况下,我们会考虑工作流服务,但是所讨论的界面正在使用中,我们有一套单元测试来测试我们的服务等。我们真的无法摆脱我们的这种实现。


所以我的问题是 -

  1. 是否可以拥有一个独立的工作流程,可以执行这个长时间运行的过程并从我们的WCF服务中调用它?
  2. 如果是,那么如何确保在IIS中执行我的服务的工作线程在工作流程的持续时间内保持活动状态?
  3. 最后,客户端无需等待此服务的响应。这是一种消防方法。当服务启动工作流并等待它完成时,客户端是否可以立即呼叫结束?

1 个答案:

答案 0 :(得分:6)

  1. 不确定。在您的WCF服务中,您将使用WorkflowApplication来执行工作流程定义。这将负责在WF运行时特定线程上使用WF运行时执行/跟踪每个WF实例(即不阻止WCF I / O线程)。
  2. 这里没有保证。如果应用程序池崩溃或计划因“不活动”而关闭,这将终止仍可能执行的任何工作流。您必须使用持久性点来确保如果WF被终止,您将从之前的书签中恢复。
  3. 是的,首先,使用[OperationContract(IsOneWay=true)]标记您的WCF服务方法。其次,您将使用1中的WorkflowApplication实例使用异步BeginRun启动WF,如果您关心跟踪WCF服务中的完成/错误,则可以注册必要的AbortedCompletedUnloaded处理程序。
  4. 这是一个非常简单的例子:

    [DataContract]
    public class MyParametersDataContract
    {
       [DataMember(Order=1, IsRequired=true)]
       public string SomeValue
       {
           get;
           set;
       }
    }
    
    public class IMyService
    {
        [OperationContract(IsOneWay=true)]
        void DoSomething(MyParametersDataContract someParameters);
    }
    
    public class MyService : IMyService
    {
         // Hold your WF definition in a static singleton to reduce overhead of activity realization
         public static readonly Lazy<MyFancyWorkflow> MyWorkflow = Lazy<MyFancyWorkflow>(() => new MyFancyWorkflow());
    
         public void DoSomething(MyParametersDataContract someParameters)
         {
             // Example of translating incoming parameters to WF args
             Dictionary<string, object> workflowInputArguments = new Dictionary<string, object>
             {
                 { "SomeArgument", someParameters.SomeValue }
             };
    
             // Create a WFA instance for this request
             WorkflowApplication workflowApplication = new WorkflowApplication(MyService.MyWorkflow.Value, workflowInputArguments);
    
             // Example of hooking the completed action
             workflowApplication.Completed = (workflowCompletedArgs) =>
             {
                 // do something when workflow has completed
             };
    
             // Invoke the running of the WF asynchronously
             Task.Factory.FromAsync(
                                    workflowApplication.BeginRun,
                                    workflowApplication.EndRun,
                                    null)
                                   .ContinueWith(runAntecdent =>
                                   {
                                      // Observe/log any exception with starting the WF so it doesn't crash the process
                                      Trace.TraceWarning("WF failed to run: " + runAntecedent.Exception.ToString());
                                   },
                                   TaskContinuationOptions.OnlyOnFaulted);
         }
    }