2011-12-16 342 views
5

私はWindowsサービスとしてセルフホストされているWCFサービスにアクセスするwinformアプリケーションを開発中です。私はサービス参照の代わりにChannelFactoryを使用しています。私はWCFサービスの接続と呼び出しに成功しています。問題は、アプリケーションを20分間アイドル状態にしてからもう一度電話をかけようとするときです。WCF ChannelFactoryと接続タイムアウトのベストプラクティス

"ソケット接続が中止されました。これは、メッセージの処理中にエラーが発生したか、リモートホストが受信タイムアウトを超過したか、またはネットワークリソースの問題が原因で発生している可能性があります。 00:00:59.9489970 '

私は接続の管理に関するベストプラクティスを探しています。私は現在、チャンネルとChannelFactoryの状態をチェックするPrepareWCFConnection(下記参照)という関数を作成しました。私はWCFサービスを呼び出す前にこのメソッドを呼び出します。これを処理するより良い方法はありますか?あなたは、すべて9 minutes.Iがデフォルトだと思うサービスをpingすることで、生きているチャネルを維持する必要がある既存のチャネルを再利用したい場合は、それが保持されている場合、チャネルが切断されますので、

 public bool PrepareWCFConnection() 
    { 
     if ((channelFactory == null) || 
      (channelFactory.State == CommunicationState.Faulted) || 
      (channelFactory.State != CommunicationState.Opened)) 
     { 
      channelFactory = new ChannelFactory<IService1>(new NetTcpBinding(), endpointAddress); 
     } 


     if ((proxy == null) || 
      (((IClientChannel)proxy).State == CommunicationState.Faulted) || 
      (((IClientChannel)proxy).State != CommunicationState.Opened)) 
     { 
      proxy = channelFactory.CreateChannel(endpointAddress); 
      ((IClientChannel)proxy).Open(); 
     } 

     return true; 
    } 
+0

より多くのテストは、それが動作しないことが判明しました。 ChannelFactoryとチャンネルの両方が開いていますが、システムをアイドル状態にしてもこのエラーが発生します。ソケット接続が中止されました。これは、メッセージの処理中にエラーが発生したか、リモートホストが受信タイムアウトを超過したか、基になるネットワークリソースの問題が原因で発生している可能性があります。ローカルソケットタイムアウトは'00:00:59.9479970 'でした。 – econner

+1

ここには、channelfactoryとチャネルの作成を示すMSDNのリンクがあります。呼び出しを行い、チャネルを閉じて、チャネルファクトリを閉じます。しかし、信用証明を使用して認証を行う場合、各メソッド呼び出しの後にチャネルを閉じて、各メソッドがリソースと時間に高価になる前にチャネルを再作成しないでください。 http://msdn.microsoft.com/en-us/library/ms734681.aspx – econner

+0

さらにテストした後、まずPrepareWCFConnection()を使用してWCFサービスへの呼び出しを開始し、次にサービスメソッドを呼び出してから(( IClientChannel)プロキシ).Close();これにより、チャネル接続が閉じられ、メソッド呼び出しごとに新しいチャネルが作成されます。これはベストプラクティスですか? – econner

答えて

4

、タイムアウトが10分で受け取りますまたは、信頼できるセッションを使用してチャンネルを有効に保つことができます。

同じチャネルでコールバックする必要がない場合は、完了したらチャネルを閉じて、サービス操作ごとに新しいチャネルを作成する方が良いでしょう。チャネルを作成するのには費用がかかりません。すべてのコールに対してチャネルを作成します。

+1

良い点:_チャンネルファクトリをキャッシュすることはできますが、すべてのコールに対してチャンネルを作成できます_。 – baraban

1

私はこの質問がかなり古いことを知っていますが、実際には答えられていないことがわかります。 2つのタイムアウトがあります(信頼性の高いメッセージングを使用しない場合は1つだけです)。サービス側では、タイムアウト期間内にアプリケーションメッセージが受信されない場合に起動される「ReceiveTimeout」があります。このタイムアウトのデフォルトは10分です。

「ReliableSession」が有効な場合にのみ使用される「InactivityTimeout」もあります。このタイムアウトは、チャネルが他の通信相手にチャネルをフォールトさせる前にメッセージを送信しないようにする最大の持続時間です。

チャンネルの寿命を延ばすには、「ReliableSession」を有効にしてから、「ReceiveTimeout」「&」「InactivityTimeout」の両方を高い値に設定することをおすすめします。 ReliableSessionは、キープアライブ(ackも送信されます)のようなILM(インフラストラクチャレベルのメッセージ)を送信することによって、チャネルを有効に保ちます。 InactivityTimeoutが期限切れになる前にキープアライブまたはALM(アプリケーションレベルのメッセージ)が受信されないと、チャネルに障害が発生します。

さらに、「ReceiveTimeout」の有効期限が切れる前にALM(アプリケーションレベルのメッセージ)が受信されなかった場合、チャネルに障害が発生します。

したがって、両方のタイムアウトを同じ値に増やすか、 "ReceiveTimeout"を "InactivityTimeout"よりも高い値に設定することをお勧めします。

「ReceiveTimeout」を設定すると、クライアント側で設定しても効果がありません。サービス側のタイムアウトのみです。

NetTcpBinding binding = new NetTcpBinding 
     { 
      ReliableSession = { Enabled = true },    
      SendTimeout = TimeSpan.FromMinutes(1) 
     }; 

     binding.ReliableSession.InactivityTimeout = TimeSpan.Parse("24.20:31:23.6470000"); 

とアプリ:サービス側でReliableSessionを使用した場合でも、クライアントはそのようにそれを実装する必要があります。サービス側の設定は次のようになります:

<bindings> 
    <netTcpBinding> 
     <binding name="netTestTcpBinding" 
       receiveTimeout="24.20:31:23.6470000"> 
     <reliableSession inactivityTimeout="24.20:31:23.6470000" 
         enabled="true" /> 
     </binding> 
    </netTcpBinding> 
    </bindings> 
<services> 
    <service> 
    <endpoint address="IServiceContract" 
       binding="netTcpBinding" 
       bindingConfiguration="netTestTcpBinding" 
       name="serviceContractTcpBinding"/> 
    <host> 
     <baseAddresses> 
      <add baseAddress="net.tcp://localhost:12001/" /> 
     </baseAddresses> 
    </host> 
    </service>     
</services> 
0

ワンかなりまっすぐ進むのソリューションをポーリングすることなく、あなたのチャネルを再利用するか、それは自分のチャンネルに最後の呼び出しの世話をしています派手なものを行うとwcfCをチェックします。 Binding.ReceiveTimeoutは、必要に応じてそれを再生するために、何かのように:上記のコードの

TimeSpan timeSpan = DateTime.Now - LastCallTime; 
    if (timeSpan.TotalSeconds > wcfC.Binding.ReceiveTimeout.TotalSeconds || wcfC.State != CommunicationState.Opened) 
    { 
     wcfC.Abort(); 
     wcfC = new WCFChannel(); 

    }  
    LastCallTime = DateTime.Now; 
関連する問題