[英]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沒什么區別。
最重要的是,無論出於何種原因,我都無法穩定回調。 是的,回調是靜態的。 除此之外,我看不到其他任何方式。
思考? 此刻我非常沮喪。
我的代碼有兩個問題,我將其發布在這里以供后代參考。
主要問題是因為我使回調彼此之間距離太近(不是一兩個)。 我注意到,在調試時,失敗是在我的do-while
循環內。 我一直在跟蹤循環內的迭代次數,以查找應用程序的狀態更改,並注意到計數器為1,而不是0。這使我意識到我需要一個延遲。 我先將兩次通話之間的延遲設置為25ms,但仍然有問題。 然后我嘗試了50ms,這解決了問題。
我必須在幾次不同的通話后添加3秒的延遲,以使鏈接不會出現故障。 我正在閱讀,這是設計使然。 據我所知,Microsoft在WCF中已采用DOS(拒絕服務)方案。 我可能會遇到這種情況,或者只是需要一些清理時間才能重置另一個調用之前的通道,盡管該參數不能解釋更長的時間。
在應用關閉時關閉頻道
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.