2011-08-25 55 views
2

我有一個Windows服務託管的WCF服務。這使用「發佈預訂」模式將事件發佈到多個訂戶。但是,我發現經過一段時間不活動後,連接失敗,並且我得到可靠的會話是錯誤的錯誤。我試圖通過更改不活動超時並接收timout設置來解決此問題,但它沒有任何區別。說實話,這讓我很生氣。WCF回調計時器

我提到過的一個解決方案是每隔一段時間就「ping」所有用戶。 (例如超時時間的一半)。

設置「ping」的最佳方式是什麼?即如何向服務添加定時器以及如何讓該定時器調用ping功能?

編輯:

我不與平的解決方案完全滿意,並希望進一步調查爲什麼我的可靠的會話保持超時。下面是該服務

服務器的app.config

<binding name="WSDualHttpBinding_IError" receiveTimeout="24.20:31:23.6470000"> 
    <reliableSession inactivityTimeout="24.20:31:23.6470000" /> 
</binding> 

客戶端的app.config

<binding name="WSDualHttpBinding_IError" closeTimeout="00:01:00" 
    openTimeout="00:01:00" receiveTimeout="24.20:31:23.6470000" 
    sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" 
    hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" 
    maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" 
    useDefaultWebProxy="true"> 
    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
     maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
    <reliableSession ordered="true" inactivityTimeout="24.20:31:23.6470000" /> 
    <security mode="Message"> 
     <message clientCredentialType="Windows" negotiateServiceCredential="true" 
      algorithmSuite="Default" /> 
    </security> 
</binding> 

我試過「無限」,而那麼這個值,但它不喜歡它的綁定配置。說,即使谷歌搜索的幾個頁面建議這樣做,該值是無效的。我只能假設這是有效的WCF/.NET的早期版本

EDIT2:

這裏是異常日誌。它絕對確實是一個隨機的時間。

************** Exception Text ************** 
System.TimeoutException: The operation did not complete within the allotted timeout of 00:00:59.4979498. The time allotted to this operation may have been a portion of a longer timeout. 

Server stack trace: 
    at System.ServiceModel.Channels.InterruptibleWaitObject.Wait(TimeSpan timeout, Boolean throwTimeoutException) 
    at System.ServiceModel.Channels.ReliableInputConnection.Close(TimeSpan timeout) 
    at System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnClose(TimeSpan timeout) 
    at System.ServiceModel.Channels.ClientReliableDuplexSessionChannel.OnClose(TimeSpan timeout) 
    at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannel.OnClose(TimeSpan timeout) 
    at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout) 

Exception rethrown at [0]: 
    at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) 
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) 
    at System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout) 
    at System.ServiceModel.ClientBase`1.System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout) 
    at System.ServiceModel.ClientBase`1.Close() 
    at MyApp.Form1.buttonError_Click(Object sender, EventArgs e) 
    at System.Windows.Forms.Control.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
    at System.Windows.Forms.Button.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
+1

您可以發佈您的配置代碼或配置文件,您可以設置超時?什麼是確切的異常和拋出異常的代碼? – Jan

+0

我已經浪費了太多的時間來解決超時問題。我只想知道如何設置ping的東西。不過謝謝。 – Jonnster

+0

@Jonnster * ping *是錯誤的方式。你會創建一個hacky的解決方案,將你咬在底部。 – oleksii

回答

2

爲了實現客戶的ping命令,你可能要採取的步驟,這個名單:

  1. 擴展了Ping方法您的回調契約(你應該已經回調合同,因爲你寫你使用發佈訂閱模式,不是嗎?):

    [OperationContract] 
    void Ping(); 
    
  2. 在客戶端調用第一連接手術後,存儲到集合中的客戶端操作方面的參考:

    List<OperationContext> _clientCtxList = new List<OperationContext>(); 
    
    void IMyService.InitSession() { 
        _clientCtxList.Add(OperationContext.Current); 
    } 
    
  3. 定義一個函數,通過你的定時器平叫所有的客戶:

    void tmrPing (object state) { 
        foreach (var ctx in _clientCtxList) 
        { 
         // todo: catch exceptions and remove client context 
         //  from list in case of failure 
         ctx.GetCallbackChannel<IMyCallbackContract>().Ping(); 
        } 
    
        // restart timer 
        _timer.Change(10000, Timeout.Infinite); 
    } 
    
  4. 定義,當你的服務啓動時啓動一個定時器(我不知道IIS託管,所以你必須給散熱鰭片d這個自己正確的位置):

    System.Threading.Timer _timer; 
    
    void Startup() { 
        // call my function in 10 seconds 
        _timer = new System.Threading.Timer(
            tmrPing, null, 10000, Timeout.Infinte); 
    } 
    

備註:

  • 這是記事本的代碼 - 它可能包含語法錯誤,可能無法編譯。不包括
  • 異常處理不包括_clineCtxList的
  • 鎖定,但強烈建議
+0

這個解決方案可以工作,但請注意以下幾點:'ping'沒有任何商業價值,但在合約中佔用空間,它需要額外的代碼,因此錯誤的概率增加,它增加了代碼的絕對不必要的複雜性,它略微增加了服務的負載,它需要文檔和進一步的代碼維護。所有這些都可以通過初始正確的綁定配置來修復。這就是爲什麼我會建議解決根本問題,而不是使用黑客。 – oleksii

+0

是的,也許。但操作明確要求ping解決方案 – Jan

+0

@oleksii - 我完全同意你的觀點,但事實是WCF很糟糕。這真的是垃圾。回顧COM,COM +和DCOM的日子。生活變得如此簡單,而且信件實際上工作了!在我看來,WCF在比較中只是垃圾。當然,我很想找到解決方案,但谷歌認爲這是一個普遍的問題,有人甚至認爲這是一個MS不會修復的已知錯誤。 – Jonnster