2011-12-16 40 views
5

我正在使用一個winform應用程序,它將訪問作爲Windows服務自行託管的WCF服務。我正在使用ChannelFactory而不是服務引用。我已經成功地連接並調用了WCF服務。問題是當我讓應用程序保持閒置20分鐘,然後嘗試撥打另一個電話。我收到以下錯誤:WCF ChannelFactory和連接超時的最佳做法

「套接字連接被中止,這可能是由於處理您的消息時出錯或遠程主機超出接收超時或基礎網絡資源問題導致的。 00:00:59.9489970' 「。

我正在尋找管理連接的最佳做法。我目前已經創建了一個名爲PrepareWCFConnection的函數(見下文),它檢查通道和ChannelFactory的狀態。我在調用WCF服務之前調用了這個方法。有沒有更好的方法來處理這個問題?

 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和channel都是打開的,但讓系統空閒後仍然出現這個錯誤:套接字連接被中止。這可能是由處理您的消息時出錯或遠程主機超出接收超時或基礎網絡資源問題引起的。本地套接字超時爲'00:00:59.9479970'。 – econner 2011-12-16 18:47:37

+1

以下是MSDN的鏈接,其中顯示了創建頻道工廠和頻道,進行調用並關閉頻道,然後關閉頻道工廠。但是,如果您使用信用卡進行身份驗證,那麼在每次方法調用之後都不會關閉信道,並且在每種方法在資源和時間上都很昂貴之前重新創建信道? http://msdn.microsoft.com/en-us/library/ms734681.aspx – econner 2011-12-16 18:50:49

回答

4

如果你想重用你需要保持通道活着查驗服務每9個minutes.I覺得默認的一個現有的頻道接收時限爲10分鐘,因此,如果保持該通道將被切斷閒置超過這個。或者你可以使用可靠的會話來保持頻道活着。

如果您不需要在同一個頻道上進行回叫,最好在完成後關閉頻道,併爲每個服務操作重新創建一個新頻道。創建頻道並不昂貴。您可以緩存渠道工廠,但爲每個呼叫創建渠道。

1

我知道這個問題現在很老了,但我看到它沒有真正得到答案。有兩個超時(如果你不使用可靠的消息傳遞,那麼只有一個超時),你應該關心什麼時候通道超時。在服務方面,如果在超時期限內沒有收到應用程序消息,則會觸發「ReceiveTimeout」。此超時的默認值爲10分鐘。

還有「InactivityTimeout」,僅在啓用「ReliableSession」時纔會使用。此超時是通道允許其他通信方在發生故障之前不發送任何消息的最長持續時間。

爲了延長頻道的使用壽命,我建議您啓用「ReliableSession」,然後將您的「ReceiveTimeout」&「InactivityTimeout」設置爲更高的值。 ReliableSession通過發送ILM(基礎設施級別的消息)(如keep-alive)(ack's也被髮送)來保持通道活動。如果在「InactivityTimeout」過期之前未收到保持活動狀態或ALM(應用程序級別消息),則通道將發生故障。

此外,如果在「ReceiveTimeout」過期之前尚未收到ALM(應用程序級消息),則通道將發生故障。

因此,建議將兩個超時值都設置爲相同的值,或將「ReceiveTimeout」設置爲比「InactivityTimeout」更高的值。

附註:設置「ReceiveTimeout」在客戶端設置時不起作用,僅在服務端超時。但是,在服務端使用時的ReliableSession,客戶端也可以實現它,像這樣:

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

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

和應用程序。在服務端的配置會是這個樣子:

<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;