双方向ワークフロー サービスのサンプル
このサンプルでは、2 つの通信サービス間での非同期双方向通信の実行方法を示します。また、メッセージを使用した localhost とワークフロー間の通信の実行方法も示します。2 つのサービス間の双方向通信を実現するには、双方向通信を実行する際に、まずサービスどうしでコンテキストを交換する必要があります。通信を開始した側のサービスは、メッセージの返信としてコンテキストを受け取ります。受信側サービスから開始側サービスへの通信をサポートするには、開始側サービスがそのコンテキスト情報を最初のメッセージで送信する必要があります。
メモ : |
---|
このサンプルをビルドして実行するには、.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 アクティビティに適用するための関数も提供されます。
サンプルを設定、ビルド、および実行するには
永続化プロバイダをインストールするには、「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」トピックの CreateStores.cmd スクリプトを実行します。
「ワークフロー サービス ユーティリティ」をダウンロードし、DuplexWorkflowService フォルダと WorkflowServiceUtility フォルダが同じ親フォルダ内に格納されるように保存します。
永続化プロバイダを使用しない場合は、App.config ファイルから
<WorkflowRuntime>
セクションをコメントアウトします。このサンプルでは、2 つの永続性データベースが使用されます。サービス ワークフローは
NetFx35Samples_ServiceWorkflowStore
という永続性データベース、クライアントはNetFx35Samples_ClientWorkflowStore
という永続性データベースをそれぞれ使用します。これらのストアは、SQL Server または SQL Server Express で作成できます。App.config ファイルに含まれている現在の接続文字列は、SQL Server Express の使用を前提としています。SQL Server でストアを作成する場合は、App.config ファイルの接続文字列を変更してください。クライアント ホストとサービス ホストが実行されたら、コンソール ウィンドウで [Y] をクリックして作業項目を処理します。複数の作業項目を送信して処理することもできます。クライアントをシャットダウンして再起動した場合は、中断した箇所から処理が再開されます。
サービスの永続性質をテストするには、クライアント アプリケーションとサービス アプリケーションの両方をシャットダウンしてから、クライアント アプリケーション、サービス アプリケーションの順に再起動します。この順序は処理シーケンスに基づいています。つまり、サービス ワークフローは実行されると同時に、クライアントへのメッセージの返信を試みます。この場合にクライアントが使用不可になっていると、例外が返されます。
クライアント上で、コンテキストは Client.ctx ファイルに保存されます。このファイルはサンプルの \bin ディレクトリに格納されます。クライアントを再度開くと、ファイルがあるかどうかが確認されます。ファイルがある場合は、格納されたコンテキストが作成中のチャネルに適用されます。ワークフロー サービスが終了している場合に、\bin ディレクトリにまだ残っている Client.ctx ファイルを使用してクライアントを開くと、チャネルへのコンテキストの適用が試みられます。この場合は、通信するワークフロー インスタンスが存在しないため、エラーが発生します。ファイルを削除して、やり直してください。
Copyright © 2007 by Microsoft Corporation.All rights reserved.