[英]Unknown exception when calling a webservice
我的系統中有兩個WCF Web服務。
Web服務A調用Web服務B。在大多數情況下,它可以正常工作。 但是,有些例程會在A調用B時引發異常:
調用的目標已引發異常。
為了試圖知道問題出在哪里,我從第一個指令到最后一個指令,在B中的被調用方法中放置了一個巨大的Try Catch。 同樣的問題。
然后,我嘗試將customErrors設置為off,將includeExceptionDetailInFaults設置為true,以獲取來自異常的詳細信息。 同樣的問題。
這不是超時問題,因為請求持續時間小於1秒。
我檢查了請求的長度,一些好的請求比不好的請求要長。 問題不在於大小。
我無法重現該問題,因為它只出現了幾次。
我認為,如果問題出在A上,則異常將比此消息包含更多詳細信息。
也許問題出在IIS上(兩者都在同一個IIS實例上),但是A通過localhost:xxxx / mywebservice.svc與B通信,因此很難相信這是一個通信問題。
編輯:
有InnerException消息:
無法訪問已處置的對象。 對象名稱:“ System.ServiceModel.Channels.ServiceChannel”。
Web服務A對B使用動態調用,使用的是: http : //blogs.msdn.com/b/vipulmodi/archive/2006/11/16/dynamic-programming-with-wcf.aspx此處的另一個鏈接: https: //github.com/carlosfigueira/WCFQuickSamples/tree/master/WCFForums/DynamicProxy
這是我的代碼:
DynamicProxy proxy = null;
[...]
proxy = FactoryTest.getProxy(sServiceWsdl, sContract);
[...]
try {
sXmlOUT = (String)proxy.CallMethod(sMethod, sXmlIN);
proxy.Close();
catch (Exception e)
{
// Here appears the exception
}
[...]
和FactoryTest類:
public sealed class FactoryTest
{
private static object syncRoot = new Object();
private static Hashtable hashFactory = new Hashtable();
public static DynamicProxy getProxy(String sServiceWsdl, String sContract)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
lock (syncRoot)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
hashFactory.Add(sServiceWsdl, new ProxyTest(sServiceWsdl, sContract));
}
}
}
return ((ProxyTest)hashFactory[sServiceWsdl]).getProxy();
}
public static bool isProxyExists(String sServiceWsdl, String sContract)
{
lock (syncRoot)
{
return hashFactory[sServiceWsdl] == null ? false : true;
}
}
}
有一個完整的異常:
調用的目標已引發異常。 在System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo方法,對象目標,Object []參數,簽名sig,MethodAttributes方法)處的System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo方法,對象目標,Object []參數,SignatureStruct&sig,MethodAttributes methodAttributes,RuntimeType typeOwner)處,位於System.Reflection.RuntimeMethodInfo.Invoke(對象obj,BindingFlags invokeAttr,活頁夾活頁夾,Object []參數,CultureInfo文化,布爾型skipVisibilityChecks)位於System.Reflection.RuntimeMethodInfo.Invoke(對象obj,BindingFlags invokeAttr,活頁夾活頁夾) ,Object []參數,CultureInfo文化)
在WS_Generic.Service.CallWsMethod(String sXmlSettings,字符串sXmlIN, String&sXmlOUT)
有完整的InnerException:
無法訪問已處置的對象。 對象名稱:“ System.ServiceModel.Channels.ServiceChannel”。
服務器堆棧跟蹤:位於System.ServiceModel.Channels.ServiceChannel.Call處System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen()處(字符串操作,布爾型單向,ProxyOperationRuntime操作,Object [] ins,Object [] outs,TimeSpan超時) System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage消息)上的System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime操作)
在[0]處拋出異常:在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&msgData,Int32類型)在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)在IWsAfsolorization.EmvTr WsAfsolClient.EmvTrxAuthorization(String sXmlIn)處的String sXmlIn)
我對您的更新進行了快速Google搜索,並在asp.net論壇上找到了這篇文章 。
我猜測(不知道您的代碼是什么樣)您有一個打開的共享連接/服務,然后在代碼中需要它時隨時調用。
選項(再次,在這里猜測而不看代碼)
根據您的最新編輯進行編輯:
在您的代碼中,您正在調用proxy.Close();。 這實際上是對Dispose的調用,但是即使對象已被處理,您也將其保留在哈希表中。 您對同一對象/服務的第二次調用(無論何時發生)將觸發您的異常。 然后,選項為1.僅在不再需要時(例如,應用程序關閉或完全在調用代碼的上下文中使用短壽命的實例時),才調用close / dispose。 為每個調用創建,使用,銷毀和忘記,並且不要將該實例保留在哈希列表中(您可以將其變成一個構建器,以為每個請求提供一個新實例)。
根據最新評論編輯#2
調用Close仍會破壞底層通道。 您可以通過連續兩次調用同一服務,並在第一次調用Close()之后立即調用GC.Collect()來進行測試,如下所示:
....
sXmlOUT = (String)proxy.CallMethod(sMethod, sXmlIN);
proxy.Close();
GC.Collect();
var sXmlOUT2 = (String)proxy.CallMethod(sMethod, sXmlIN); // should trigger your exception
...
這是一種重構代碼的方法。
public class SomeClass
{
FactoryTest factory; // instantiate this somewhere like constructor
public void someMethod()
{
[...]
var proxy = factory.getProxy(sServiceWsdl, sContract);
[...]
try {
sXmlOUT = (String)proxy.CallMethod(sMethod, sXmlIN);
// proxy.Close(); - do not close connection
catch (Exception e)
{
// Here appears the exception
}
}// end method
}// end class
// optionally if you want the same instance to server other callers
// you can turn this into a Singleton pattern and return a shared
// static instance of FactoryTest via a static method. Do not forget to
// dispose of the singleton at the end of your application
public sealed class FactoryTest : IDisposable
{
private object syncRoot = new Object();
private Hashtable hashFactory = new Hashtable();
public DynamicProxy getProxy(String sServiceWsdl, String sContract)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
lock (syncRoot)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
hashFactory.Add(sServiceWsdl, new ProxyTest(sServiceWsdl, sContract));
}
}
}
return ((ProxyTest)hashFactory[sServiceWsdl]).getProxy();
}
public bool isProxyExists(String sServiceWsdl, String sContract)
{
lock (syncRoot)
{
return hashFactory[sServiceWsdl] == null ? false : true;
}
}
public void Dispose()
{
// implement IDisposable
// dispose of everything hashFactory using Close() or Dispose()
}
} // end class
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.