1

.configファイルに基づいてServiceHostsを動的に作成する小さなWCFホスティングエンジンを作成しています。一般的な考え方は、すべてのサービスをオフラインにすることなく、実行時に既存のサービスを削除したり、新しいサービスを追加したりできるようにすることです。

問題のあるユニットテストに遭遇しました。これは、これが思ったほど簡単ではない可能性があることを示しています。特定のエンドポイントには1つのServiceHostしか存在しないようです(サービスの複数の異なるエンドポイントが1つのServiceHostに存在する場合でも)。これは通常は問題ではありませんが、サービスを再構成する必要がある場合、元のServiceHostを停止しても、実際にはそのエンドポイントアドレスの登録が強制終了されることはありません。同じサービス(つまり、同じエンドポイントが使用されている)に対して別のServiceHostを作成しようとすると、次の例外が発生して失敗します。

System.InvalidOperationException: The ChannelDispatcher at 'net.pipe://localhost/' with contract(s) '"ITestService"' is unable to open its IChannelListener. --->
System.InvalidOperationException: A registration already exists for URI 'net.pipe://localhost/'.

ユニットテスト中に実際にエラーが発生しています。テストでは1つのユニットを実行します。これにより、ServiceHostsとホスティングエンジンが人間的に可能な限り完全にシャットダウンされます。次に、ホスティングエンジンの別のインスタンスを作成します。このインスタンスは、別のテストのために同じServiceHostsを再作成しようとします。2番目のテストでは、上記のエラーが発生します。ServiceHost.Close()が呼び出されている間、それは実際にはサービスホストを破棄しないと推測しています...したがって、それはまだメモリ内でぶら下がっています。GCが古いサービスホストをクリーンアップしているかどうかはわかりません...問題は最初に発生した後も解消されずに解決しません(私が判断できたのは最善です...これまで約30分待っていました。 )。

system.serviceModelの構成ファイルは次のとおりです。

  <system.serviceModel>
    <services>
      <service name="Campus.Core.ServiceModel.TestServiceStub">
        <endpoint          
          address="net.pipe://localhost"          
          binding="netNamedPipeBinding"           
          contract="Campus.Core.ServiceModel.ITestService"
        />
      </service>
    </services>
  </system.serviceModel>
4

2 に答える 2

3

他の誰かが問題に遭遇した場合に備えて、この質問に対する回答を提供します。この問題には、実際には次の 2 つの原因があることが判明しました。

1) 単体テスト中に例外が発生した場合、通常は ServiceHost を閉じる前にテスト中のコードから抜け出します。これにより、ServiceHost が特定のエンドポイントにバインドされたままになります。これにより、同じコードを実行する後続のすべてのテストが失敗しました。SubSpec と xUnit を使用して BDD を行っていたので、1 つのテスト ケース (BDD 用語での懸念) はテストごとに 1 つのアサーションを実行し、1 つのテスト ケースには最大で 12 以上のアサーションを含めることができました。

2) MEX エンドポイントに注意してください。MEX エンドポイントは、サービスごとに 1 回だけ存在できます。最初に、http と net.tcp mex エンドポイントを作成しました。ただし、これにより、2 番目に起動された MEX エンドポイントのインスタンスが例外をスローしたため、問題が発生しました。一般的に言えば、MEX エンドポイントを利用する場合、使用を妨げる物理的なインフラストラクチャの問題がない限り、HTTP が最も有用なプロトコルです。

一般的に言えば、ServiceHost で Close() メソッドを呼び出すと完全にアンバインドされ、以前にエンドポイントにバインドされていたアドレスが再び使用できるようになります。クローズには時間がかかる場合があり、まれに例外がスローされる場合があります。SubSpec を使用して BDD を実行し、テストごとに 1 つのアサーションのルールに従っている場合、1 つのテストで ServiceHosts クロージャーを妨げる例外がスローされると、後続のすべてのテストが失敗します。

于 2009-11-11T05:31:46.820 に答える
1

1 つの答えは、サービス ホストをスピンアップするたびにサービス ホストの URL に Guid を追加し、ServiceHost インスタンスをスピンアップしてクライアント側チャネルを返すファクトリ アプローチを使用することです。これにより、クライアントは使用する URL を認識できます。 .

IDesign の InProcFactory サンプルはこのアプローチを使用しているため、そのまま使用できる場合があります。

http://www.idesign.net/idesign/DesktopDefault.aspx?tabindex=5&tabid=11

サンプルをダウンロードするには、IDesign のサイトに登録する必要があることに注意してください。また、トレーニングなどに関するアナウンスが時々送られてきますが、それほど多くはありません。

于 2009-09-11T17:08:35.020 に答える