簡體   English   中英

WCF ServiceHost回調不穩定

[英]WCF ServiceHost Callback Unstable

問題

最可再現的方案是從任務欄應用程序上的鏈接啟動桌面應用程序,然后通過回調請求桌面應用程序執行某項操作。 實際上,這總是會引發超時錯誤以及其他后續錯誤。

WCF環境:

服務器:系統托盤小程序

客戶端:WinForms桌面應用程序

資源:

從托盤啟動桌面應用程序的方法

// Start the process.
ProcessStartInfo oProcessInfo = new ProcessStartInfo()
{
    FileName = regValue.ToString(),
    WindowStyle = ProcessWindowStyle.Normal,
    UseShellExecute = true,
    CreateNoWindow = false,
};
Process oProcess = new Process()
{
    StartInfo = oProcessInfo,
};
oProcess.Start();

我打了幾個電話,但是互動並不一定會在第一個電話上失敗。 這是一個示例調用:

var callback = IpcToTray.Callback;
if (null == callback)
    return 0;

UInt16 idIsLaunched = callback.IsAppLaunched();
if (Id_AppIsLaunched == idIsLaunched)
    return true;

我目前正在使用PerCall,但正在使用PerSession。 兩者均無濟於事。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class IpcToTray : IIpcToTray
{
}

以下是一些錯誤:

System.TimeoutException
  HResult=0x80131505
  Message=This request operation sent to http://schemas.microsoft.com/2005/12/ServiceModel/Addressing/Anonymous did not receive a reply within the configured timeout (00:00:10).  The time allotted to this operation may have been a portion of a longer timeout.  This may be because the service is still processing the operation or because the service was unable to send a reply message.  Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.
  Source=mscorlib
  StackTrace:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at MyAppIpc.IIpcCallbackToTray.GetMyAppMode()
   at MyAppTray.Communication.IpcFromTray.GetMyAppMode() in ...\IpcFromTray.cs:line 194

System.ObjectDisposedException
  HResult=0x80131622
  Message=Cannot access a disposed object.
Object name: 'System.ServiceModel.ServiceHost'.
  Source=System.ServiceModel
  StackTrace:
   at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrImmutable()
   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open()
   at MyAppTray.CustomApplicationContext.StartPipeServer() in ...\MyAppTray\CustomApplicationContext.cs:line 105

System.ServiceModel.CommunicationObjectAbortedException
  HResult=0x80131501
  Message=The operation 'IsAppLaunched' could not be completed because the sessionful channel timed out waiting to receive a message.  To increase the timeout, either set the receiveTimeout property on the binding in your configuration file, or set the ReceiveTimeout property on the Binding directly.
  Source=mscorlib
  StackTrace:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at MyAppIpc.IIpcCallbackToTray.IsAppLaunched()
   at MyAppTray.Communication.IpcFromTray.IsAppLaunched() in ...\MyAppTray\Communication\IpcFromTray.cs:line 142

對於我的代碼,它基本上看起來像是WCF進程間通信示例,但類名稱已更改,但其他方面相似,因此無需在此處放置。

我嘗試在失敗后重新啟動,但是.Close()后跟.Open()並不總是可以正常工作,這可能是被創建的,創建新的URI端點已經存在。 我嘗試了許多方法來使事情穩定無濟於事。

我現在有10秒鍾的超時時間。 原始超時為1分鍾,這是Microsoft的默認設置。 我以為我的應用程序一開始就掛了。 會話內容無濟於事。 我嘗試添加一個延遲Thread.Sleep(4000),但這很煩人,什么也不做。 該應用程序可能是打開的,但是再次休眠4000或4000000000000沒什么區別。

最重要的是,無論出於何種原因,我都無法穩定回調。 是的,回調是靜態的。 除此之外,我看不到其他任何方式。

思考? 此刻我非常沮喪。

我的代碼有兩個問題,我將其發布在這里以供后代參考。

  1. 延遲/ DOS

主要問題是因為我使回調彼此之間距離太近(不是一兩個)。 我注意到,在調試時,失敗是在我的do-while循環內。 我一直在跟蹤循環內的迭代次數,以查找應用程序的狀態更改,並注意到計數器為1,而不是0。這使我意識到我需要一個延遲。 我先將兩次通話之間的延遲設置為25ms,但仍然有問題。 然后我嘗試了50ms,這解決了問題。

我必須在幾次不同的通話后添加3秒的延遲,以使鏈接不會出現故障。 我正在閱讀,這是設計使然。 據我所知,Microsoft在WCF中已采用DOS(拒絕服務)方案。 我可能會遇到這種情況,或者只是需要一些清理時間才能重置另一個調用之前的通道,盡管該參數不能解釋更長的時間。

  1. 在應用關閉時關閉頻道

     this.HostIpcToTray.CloseCallback(); this.IpcPipeFactory.Close(); private void IpcPipeFactory_Closing(object sender, EventArgs e) { this.IsConnectedPipeToTray = false; this.HostIpcToTray = null; this.IpcPipeFactory.Closing -= IpcPipeFactory_Closing; } 

第一次調用將靜態Callback變量設置為null,以便該服務在下一次應用程序啟動之前不能使用已處置的對象。

我必須取消訂閱Closing事件,而這是在Closing事件中進行的。

我調用了Close()通道,但我沒有這樣做。 我猜垃圾回收不能正確關閉通道。 當我嘗試關閉主應用程序(客戶端),然后再次啟動該應用程序並使用任務欄傳達我拋出了故障時,我注意到了這個問題。 經過一些研究,得出了上面的代碼。

許多示例顯示了WCF IPC的基本框架,但細節在於生產代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM