双方向ワークフロー サービスのサンプル

Download sample

このサンプルでは、2 つの通信サービス間での非同期双方向通信の実行方法を示します。また、メッセージを使用した localhost とワークフロー間の通信の実行方法も示します。2 つのサービス間の双方向通信を実現するには、双方向通信を実行する際に、まずサービスどうしでコンテキストを交換する必要があります。通信を開始した側のサービスは、メッセージの返信としてコンテキストを受け取ります。受信側サービスから開始側サービスへの通信をサポートするには、開始側サービスがそのコンテキスト情報を最初のメッセージで送信する必要があります。

Noteメモ :

このサンプルをビルドして実行するには、.NET Framework Version 3.5 をインストールする必要があります。プロジェクト ファイルとソリューション ファイルを開くには、Visual Studio 2008 が必要です。

このサンプルのセットアップの詳細については、「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」を参照してください。

メッセージは、ローカルホストとサービス間の通信にも使用されます。ローカルホストは、サービスがコールバックに使用できる既知のエンドポイントを公開します。このサンプルでは、ローカル リスナだけでなく、ホストされるサービスのワークフロー サービス ホストも作成する機能を備えた LocalWorkflowServiceHost 型が実装されます。

双方向ワークフロー サービスのサンプル アーキテクチャ

このサンプルは、次の通信エンティティで構成されます。

  • クライアント ホスト

    クライアント ホストは、IReverseContract に対して操作を呼び出すことによって、クライアント ワークフローと通信します。クライアント ホストが BeginWork 操作を初めて呼び出したときに、クライアント ワークフローが作成されます。クライアント ワークフローは、BeginWork 操作に対する応答として、クライアント ワークフローに関するコンテキストが含まれたメッセージを返信します。クライアント ワークフローとの通信のためにホストが作成するチャネルには、さらなる通信のためのコンテキストが含まれるようになります。このサンプルでは、クライアント ホストが同じチャネルを使用して、複数の作業項目をクライアント ワークフローに送信するしくみを示します。

    ワークフローがクライアント ホストと通信できるよう、クライアント ホストには、待機する既知のエンドポイントがあります。このサンプルの場合、既知のエンドポイントは HostEndPoint という名前です。LocalWorkflowServiceHost は、クライアント ホストに対するこの既知のエンドポイントと、クライアント ワークフローに対するワークフロー サービス ホストを作成するために使用されます。

    LocalWorkflowServiceHost localHost = new LocalWorkflowServiceHost(typeof(ClientWorkflow),new ClientHost());
    localHost.WorkflowRuntime.WorkflowTerminated += 
    delegate(object sender, WorkflowTerminatedEventArgs e) 
    {
        Console.WriteLine("WorkflowTerminated: " + e.Exception.Message);
    };
    localHost.WorkflowRuntime.WorkflowCompleted += 
    delegate(object sender, WorkflowCompletedEventArgs e) 
    { 
        Console.WriteLine("WorkflowCompleted: " + 
                         e.WorkflowInstance.InstanceId.ToString()); 
    };
    localHost.Open();
    
  • クライアント ワークフロー (サービスとして公開)

    クライアント ワークフローは、IReverseContract を実装します。サービス ワークフローは、前の図に示すように、クライアント ワークフローと通信するためにこれを使用します。クライアント ワークフローが BeginWorkflow 操作を初めて呼び出すと、サービス ワークフローが作成されます。その応答としてサービス ワークフローに関するコンテキストが返され、このコンテキストは、サービス ワークフローとの後続のクライアント ワークフロー通信で使用されます。クライアント ワークフローは、BeginWorkflow 操作の一環として独自のエンドポイント参照を渡します。このエンドポイント参照には、エンドポイントのアドレスだけでなく、サービス ワークフローに対するコンテキスト ヘッダーも含まれています。サービス ワークフローは、このエンドポイント アドレスを使用して、クライアント ワークフローと非同期で通信します。

    初期状態の WaitForBeginWork イベント ハンドラは、DoSetReturnAddress というコード アクティビティを実装します。このアクティビティは、次のサンプルに示すように、サービス ワークフローに送信されるエンドポイント参照を設定します。

    private void SetReturnAddress(object sender, EventArgs e)
    {
        EndpointAddress epr = 
                  ContextManager.CreateEndpointAddress(ReturnUri, 
                                  this.ReceiveWorkItemComplete);
        ReturnAddress = EndpointAddress10.FromEndpointAddress(epr);
        DebugOutput("[ClientWorkflow:SetReturnAddress] " + 
                              epr.Headers[0].GetValue<string>());
    }
    
  • サービス ホスト

    このサンプルでは、ワークフロー サービス ホストが実装され、クライアントからの要求を待機するリスナが開かれます。クライアントからの最初の要求を受信すると、サービス ワークフローのインスタンスが作成されます。要求のコンテキストはメッセージ ヘッダーに含まれているので、2 番目以降の要求はすべて、これと同じワークフロー インスタンスにルーティングされます。

  • サービス ワークフロー (サービスとして公開)

    サービス ワークフローは、IForwardContract を実装します。BeginWorkflow 操作のサービス ワークフローは、クライアント ワークフローのエンドポイント参照を受信します。サービス ワークフローは、このエンドポイント参照を、クライアント ワークフローにメッセージを非同期で送信する Send アクティビティに適用します。WaitForBeginWorkflow イベント ハンドラは、BeginWorkflow の Receive アクティビティを提供します。この Receive アクティビティの中には、ApplyReturnAddress というコード アクティビティが含まれています。このコード アクティビティは、次のコードに示すように、Send アクティビティ内のリターン アドレスを使用して、クライアント ワークフローにメッセージを送信します。

    private void ApplyReturnAddress(object sender, EventArgs e)
    {
        // apply ReturnAddress to ReverseEndpoint
        EndpointAddress epr = ReturnAddress.ToEndpointAddress();
        ContextManager.ApplyEndpointAddress(
                              this.SendWorkItemComplete, epr);
        DebugOutput("[ServiceWorkflow:ApplyReturnAddress] " + 
                           epr.Headers[0].GetValue<string>());
    }
    

    LocalWorkflowServiceHost クラスは、ホストとワークフロー間の通信に必要なインフラストラクチャを作成します。ローカル ワークフロー サービスは、次の 2 つの主要タスクを実行します。

    • ホストがワークフローからのメッセージを待機するために使用するローカル リスナを作成します。

    • ワークフローのリスナを作成するための WorkflowServiceHost をインスタンス化します。

    このクラスでは、ワークフローとの通信に使用するコンテキストを管理するためのヘルパー関数もホストに対して提供されます。ホストがリサイクルされる場合、このコンテキストはワークフロー インスタンスと通信するために使用されます。

WorkflowServiceUtility プロジェクトでは、コンテキストを操作するために必要なすべてのヘルパー関数が提供されます。また、チャネルからコンテキストを抽出し、コンテキストをチャネルに適用して、エンドポイント アドレスを Send アクティビティに適用するための関数も提供されます。

サンプルを設定、ビルド、および実行するには

  1. 永続化プロバイダをインストールするには、「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」トピックの CreateStores.cmd スクリプトを実行します。

  2. ワークフロー サービス ユーティリティ」をダウンロードし、DuplexWorkflowService フォルダと WorkflowServiceUtility フォルダが同じ親フォルダ内に格納されるように保存します。

  3. 永続化プロバイダを使用しない場合は、App.config ファイルから <WorkflowRuntime> セクションをコメントアウトします。

  4. このサンプルでは、2 つの永続性データベースが使用されます。サービス ワークフローは NetFx35Samples_ServiceWorkflowStore という永続性データベース、クライアントは NetFx35Samples_ClientWorkflowStore という永続性データベースをそれぞれ使用します。これらのストアは、SQL Server または SQL Server Express で作成できます。App.config ファイルに含まれている現在の接続文字列は、SQL Server Express の使用を前提としています。SQL Server でストアを作成する場合は、App.config ファイルの接続文字列を変更してください。

  5. クライアント ホストとサービス ホストが実行されたら、コンソール ウィンドウで [Y] をクリックして作業項目を処理します。複数の作業項目を送信して処理することもできます。クライアントをシャットダウンして再起動した場合は、中断した箇所から処理が再開されます。

  6. サービスの永続性質をテストするには、クライアント アプリケーションとサービス アプリケーションの両方をシャットダウンしてから、クライアント アプリケーション、サービス アプリケーションの順に再起動します。この順序は処理シーケンスに基づいています。つまり、サービス ワークフローは実行されると同時に、クライアントへのメッセージの返信を試みます。この場合にクライアントが使用不可になっていると、例外が返されます。

  7. クライアント上で、コンテキストは Client.ctx ファイルに保存されます。このファイルはサンプルの \bin ディレクトリに格納されます。クライアントを再度開くと、ファイルがあるかどうかが確認されます。ファイルがある場合は、格納されたコンテキストが作成中のチャネルに適用されます。ワークフロー サービスが終了している場合に、\bin ディレクトリにまだ残っている Client.ctx ファイルを使用してクライアントを開くと、チャネルへのコンテキストの適用が試みられます。この場合は、通信するワークフロー インスタンスが存在しないため、エラーが発生します。ファイルを削除して、やり直してください。

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.