このサンプルでは、2 つの通信サービス間での非同期双方向通信の実行方法を示します。また、メッセージを使用した localhost とワークフロー間の通信の実行方法も示します。2 つのサービス間の双方向通信を実現するには、双方向通信を実行する際に、まずサービスどうしでコンテキストを交換する必要があります。通信を開始した側のサービスは、メッセージの返信としてコンテキストを受け取ります。受信側サービスから開始側サービスへの通信をサポートするには、開始側サービスがそのコンテキスト情報を最初のメッセージで送信する必要があります。
メモ : |
|---|
このサンプルをビルドして実行するには、.NET Framework Version 3.5 をインストールする必要があります。プロジェクト ファイルとソリューション ファイルを開くには、Visual Studio 2008 が必要です。 |
このサンプルのセットアップの詳細については、「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」を参照してください。
メッセージは、ローカルホストとサービス間の通信にも使用されます。ローカルホストは、サービスがコールバックに使用できる既知のエンドポイントを公開します。このサンプルでは、ローカル リスナだけでなく、ホストされるサービスのワークフロー サービス ホストも作成する機能を備えた LocalWorkflowServiceHost 型が実装されます。
.gif)
このサンプルは、次の通信エンティティで構成されます。
クライアント ホスト
クライアント ホストは、
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 ファイルを使用してクライアントを開くと、チャネルへのコンテキストの適用が試みられます。この場合は、通信するワークフロー インスタンスが存在しないため、エラーが発生します。ファイルを削除して、やり直してください。
.gif)
Copyright © 2007 by Microsoft Corporation.All rights reserved.
メモ :