2012-03-20 108 views
1

我有一个定义良好的服务合约,它公开了一堆方法。我们有一个典型的服务实现这个合同,它与我们的MVC App一起被托管在IIS 7中。从WCF服务调用WF工作流程

该体系结构是典型的分布式应用程序,其接口在基本核心库(可重新分发)中定义,独立服务库中的实现以及最终MVC应用程序暴露了实现的端点它位于服务库内)。

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


所以我的问题是 -

  1. 是否有可能有一个独立的工作流,可以做到这一点长时间运行的进程,从我们的WCF服务调用它呢?
  2. 如果是这样,那么我如何确保在IIS中执行我的服务的工作线程在工作流的持续时间内保持活动状态?
  3. 最后客户端不需要等待这个服务的响应。这是一种失火和遗忘的方法。当服务启动工作流并等待它完成时,客户端调用是否可以立即结束?

回答

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

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

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

感谢德鲁。只是我在寻找的那种东西。然而,在“//在工作流完成时做些事情”一点,鉴于这是一个WCF服务,我该如何提供一个回调方法(可能在相同的服务中定义)?我的WCF服务的新实例是否会创建,并在WF完成时调用回调方法? – Nikhil 2012-03-21 23:49:53

+0

哦,是的,所以如果你想做回调,你只需在回调闭包中捕获客户端回调通道(OperationContext.Current.GetCallbackChannel ()),然后调用回调方法即可。 – 2012-03-22 00:04:07

+0

即使我还没有机会尝试这种方法,我会将其标记为答案。它似乎确实会起作用! – Nikhil 2012-03-27 10:05:39