2011-07-11 7 views
1

を作成し、複数のWorkflowServiceHostインスタンスを使用してエンジンをホスティングしています。スケジュールされた間隔で起動する、つまりアクティビティを遅延させてジョブを実行し、キャッシュにデータを読み込む、長時間実行するワークフローを作成しました。これらのワークフローは、IIS 7でホストされるカスタムWCFデータサービスであるメインアプリケーションから開始されます。ワークフローを開始するトリガは、User Login、特定のエンティティのRequestから異なります。ワークフローは、私は次のことを達成しようとしています動的

現在、私は標準のリクエスト契約の一部であるトリガをリッスンWCFワークフローサービスを、作成しました。受信したトリガは、アクティビティ定義でWorkflowApplicationをインスタンス化し、ワークフローを開始します。これは、永続性と再水和が手動で行われなければならないので、これには限界があります。

私たちはWebファーム環境を持っているように、フェイルオーバー時に持続性と再水和をサポートするホストとして動作することができWorkflowServiceHostのサンプル、出くわしました。しかし、私が以下のようなことをしようとすると、さまざまなエラーで失敗します。だから、私が正しい方向に進んでいるかどうかを知りたがっているだけです。またはこれは不可能です。 MSDNのサンプルに基づいてIWorkflowCreation契約の実装コードを見つけてください:

` public Guid StartWorkflowReturnGuid(Dictionary<string,object> parameters) 
     { 
      Guid id = Guid.Empty; 
      try 
      { 


      System.ServiceModel.Activities.WorkflowServiceHost host = new System.ServiceModel.Activities.WorkflowServiceHost(this.workflow, new Uri("net.pipe://localhost")); 

      //string myConnectionString = 
      // "Data Source=localhost\\SQLEXPRESS;Initial Catalog=DefaultSampleStore;Integrated Security=True;Asynchronous Processing=True"; 
      //SqlWorkflowInstanceStoreBehavior sqlWorkflowInstanceStoreBehavior = 
      // new SqlWorkflowInstanceStoreBehavior(myConnectionString); 
      //sqlWorkflowInstanceStoreBehavior.HostLockRenewalPeriod = TimeSpan.FromSeconds(30); 
      //sqlWorkflowInstanceStoreBehavior.RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(30); 
      //host.Description.Behaviors.Add(sqlWorkflowInstanceStoreBehavior); 

      WorkflowUnhandledExceptionBehavior workflowUnhandledExceptionBehavior = 
       new WorkflowUnhandledExceptionBehavior(); 

      workflowUnhandledExceptionBehavior.Action = WorkflowUnhandledExceptionAction.Terminate; 

      //Set the TimeToUnload to 0 to force the WF to be unloaded. To have a durable delay, the WF needs to be unloaded otherwise it will be thread as an in-memory delay. 
      //WorkflowIdleBehavior workflowIdleBehavior = new WorkflowIdleBehavior() 
      //{ 
      // TimeToUnload = TimeSpan.FromSeconds(0) 
      //}; 
      //host.Description.Behaviors.Add(workflowIdleBehavior); 
      host.WorkflowExtensions.Add(new LoginExtensions()); 
      host.WorkflowExtensions.Add(new MarketDataExtensions()); 
      ResumeBookmarkEndpoint endpoint = new ResumeBookmarkEndpoint(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(string.Format("net.pipe://localhost/workflowCreationEndpoint/{0}",Guid.NewGuid()))); 
      host.AddServiceEndpoint(endpoint); 
      host.Open(); 
      IWorkflowCreation client = new ChannelFactory<IWorkflowCreation>(endpoint.Binding, endpoint.Address).CreateChannel(); 
      //create an instance 
      id = client.Create(parameters); 
      Helper.LogInfo(string.Format("Workflow instance {0} created", id)); 
      } 
      catch (Exception exception) 
      { 

       Helper.LogError(string.Format("Exception starting BatchWorkflowServiceHost for type {0}", this.workflow.GetType().FullName), exception); 
      } 
      return id; 
     } 
public class ResumeBookmarkEndpoint : WorkflowHostingEndpoint 
{ 

    public ResumeBookmarkEndpoint(Binding binding, EndpointAddress address) 
     : base(typeof(IWorkflowCreation), binding, address) 
    { 
    } 

    protected override Guid OnGetInstanceId(object[] inputs, OperationContext operationContext) 
    { 
     //Create called 
     if (operationContext.IncomingMessageHeaders.Action.EndsWith("Create")) 
     { 
      return Guid.Empty; 
     } 
     //CreateWithInstanceId or ResumeBookmark called. InstanceId is specified by client 
     else if (operationContext.IncomingMessageHeaders.Action.EndsWith("CreateWithInstanceId")|| 
       operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark")) 
     { 
      return (Guid)inputs[0]; 
     } 
     else 
     { 
      throw new InvalidOperationException("Invalid Action: " + operationContext.IncomingMessageHeaders.Action); 
     } 
    } 


    protected override WorkflowCreationContext OnGetCreationContext(object[] inputs, OperationContext operationContext, Guid instanceId, WorkflowHostingResponseContext responseContext) 
    { 
     WorkflowCreationContext creationContext = new WorkflowCreationContext(); 
     if (operationContext.IncomingMessageHeaders.Action.EndsWith("Create")) 
     { 
      Dictionary<string, object> arguments = (Dictionary<string, object>)inputs[0]; 
      if (arguments != null && arguments.Count > 0) 
      { 
       foreach (KeyValuePair<string, object> pair in arguments) 
       { 
        //arguments for the workflow 
        creationContext.WorkflowArguments.Add(pair.Key, pair.Value); 
       } 
      } 
      //reply to client with the InstanceId 
      responseContext.SendResponse(instanceId, null); 
     } 
     else if (operationContext.IncomingMessageHeaders.Action.EndsWith("CreateWithInstanceId")) 
     { 
      Dictionary<string, object> arguments = (Dictionary<string, object>)inputs[0]; 
      if (arguments != null && arguments.Count > 0) 
      { 
       foreach (KeyValuePair<string, object> pair in arguments) 
       { 
        //arguments for the workflow 
        creationContext.WorkflowArguments.Add(pair.Key, pair.Value); 
       } 
      } 
     } 
     else 
     { 
      throw new InvalidOperationException("Invalid Action: " + operationContext.IncomingMessageHeaders.Action); 
     } 
     return creationContext; 
    } 
    protected override System.Activities.Bookmark OnResolveBookmark(object[] inputs, OperationContext operationContext, WorkflowHostingResponseContext responseContext, out object value) 
    { 
     Bookmark bookmark = null; 
     value = null; 
     if (operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark")) 
     { 
      //bookmark name supplied by client as input to IWorkflowCreation.ResumeBookmark 
      bookmark = new Bookmark((string)inputs[1]); 
      //value supplied by client as argument to IWorkflowCreation.ResumeBookmark 
      value = (string) inputs[2]; 
     } 
     else 
     { 
      throw new NotImplementedException(operationContext.IncomingMessageHeaders.Action); 
     } 
     return bookmark; 
    } 
} 

//ServiceContract exposed on the endpoint 
[ServiceContract(Name = "IWorkflowCreation")] 
public interface IWorkflowCreation 
{ 
    [OperationContract(Name = "Create")] 
    Guid Create(IDictionary<string, object> inputs); 

    [OperationContract(Name = "CreateWithInstanceId", IsOneWay=true)] 
    void CreateWithInstanceId(Guid instanceId, IDictionary<string, object> inputs); 

    [OperationContract(Name = "ResumeBookmark", IsOneWay = true)] 
    void ResumeBookmark(Guid instanceId, string bookmarkName, string message); 

} 

答えて

1

確かに可能です。しかしあなたの質問は質問を提起します。 WCFワークフローサービスがあるとします。つまり、既にWorkflowServiceHostを使用しています。

は限りWorkfowServiceHostを使用するのとなります。 IWorkflowCreationを使用してワークフローを独自に作成および管理することは可能ですが、何をすべきかに関するサンプルがありますが、通常の方法はWCF-WF4インフラストラクチャを使用してワークフローを作成することです。ワークフローを作成し、受信アクティビティを追加してCanCreateInstanceをtrueに設定し、そのアクティビティにWCFリクエストを送信すると、新しいワークフローインスタンスが作成されます。

あなたも可能である永続性を持つWorklflowApplicationを使用したいが、その後、各インスタンスを自分で管理する必要がある場合。自動リロードはありません。個々のインスタンスを管理する必要がある場合、どのようにしてタイムアウトが発生していないかを確認し、インスタンスを再開することができます。フェールオーバーも同様に機能し、同じSqlWorkflowInstanceStoreを使用してワークフロー状態の実際の保存と読み込みを行います。

+0

あなたは正しいです。私は当初AppFabric統合を利用するためにWCF Workflow Serviceを使用する予定でしたが、特定のユーザーイベントに基づいてワークフローまたはカスタムアクティビティ(XAML)を動的にインスタンス化する必要があるため、AppFabricを活用する複数の送信/受信ペアのモデルインフラ。その結果、WorkflowApplicationベースのホスティングモデルを使用しました。これは、ワークフローの自動再水和をサポートしていないことを正しく示していますが、期限切れのタイマーをポーリングするロジックを実装する必要があります。したがって、どのように私はWorkflowServiceHostベースのモデルをそれを達成するために持っているのですか? –

+0

上記のコメントは –

+1

でした。CanCreateInstance = trueのワークフローでIWorkflowCreationとReceiveActivityを実行しようとすると、メッセージ:例外ABC.Precaching.Workflow.Activities.ValidateTokenJobのBatchWorkflowServiceHostが開始されます。 例外メッセージ: 'ValidateTokenJob'エンドポイント。これは、アプリケーションに設定ファイルが見つからなかったか、またはサービス名に一致するサービス要素が構成ファイルに見つからないか、またはサービス要素にエンドポイントが定義されていないことが原因です。それは期限切れのタイマーのポーリングを開始するためにWorkflowApplicationについてコメントで –

関連する問題