【问题标题】:Invoke a WF Workflow from WCF Service从 WCF 服务调用 WF 工作流
【发布时间】:2012-03-21 07:37:41
【问题描述】:

我有一个定义明确的服务合同,它公开了一堆方法。我们有这个合同的典型服务实现,它与我们的 MVC 应用程序一起托管在 IIS 7 中。

该架构是典型的分布式应用程序,其接口定义在基础核心库中(可重新分发),实现在独立服务库中,最后是 MVC 应用程序公开实现的端点(其中位于服务库中)。

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


所以我的问题是 -

  1. 是否可以有一个独立的工作流来执行这个长时间运行的过程并从我们的 WCF 服务中调用它?
  2. 如果是这样,我如何确保在 IIS 中执行我的服务的工作线程在工作流期间保持活动状态?
  3. 最终客户端不需要等待该服务的响应。这是一种“一劳永逸”的方法。服务启动工作流并等待其完成时,客户端调用能否立即结束?

【问题讨论】:

    标签: wcf workflow-foundation-4


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

    这是一个非常简单的例子:

    [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);
         }
    }
    

    【讨论】:

    • 谢谢德鲁。正是我一直在寻找的那种东西。但是,在“//在工作流完成后做某事”位中,鉴于这是 WCF 服务,我如何提供回调方法(可能在同一服务中定义)?是否会创建我的 WCF 服务的新实例并在 WF 完成时调用回调方法?
    • 哦,是的,所以如果你想做一个回调,你只需在回调闭包中捕获客户端回调通道 (OperationContext.Current.GetCallbackChannel()),然后调用回调方法.
    • 我将把它标记为答案,即使我还没有机会端到端地尝试这个。看来它确实会起作用!
    • Nikhil - 你能成功吗?我正在研究类似的东西,想看看你到目前为止的体验如何?
    • 嘿,突变体,我们实际上走上了不同的切线。我在这里解释得有点多,但本质上我们暴露了一个“假服务端点”,它在 CustomBinding 上启动一个工作流服务主机。这给了我们两全其美的优势,我们可以在本地使用 SQLPersistence 等。我计划在另一个 StackOverflow 线程上的某个人想要这个示例时,尽快在我的博客 nikgupta.net 上上传一个示例代码
    猜你喜欢
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    相关资源
    最近更新 更多