簡體   English   中英

調用Web服務時出現未知異常

[英]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論壇上找到了這篇文章

我猜測(不知道您的代碼是什么樣)您有一個打開的共享連接/服務,然后在代碼中需要它時隨時調用。

選項(再次,在這里猜測而不看代碼)

  1. 在進行呼叫之前,請檢查服務的狀態,以查看其是否准備好/可以被呼叫。 如果關閉,則創建一個新實例。 銷毀/創建的共享資源的問題在於,除非使進程成為線程安全的,否則該進程不是線程安全的。
  2. (我采取的方式)始終創建一個新實例,並在每次調用時將其關閉,並讓基礎框架處理連接池。 服務連接僅在使用它的方法內部具有作用域。

根據您的最新編輯進行編輯:

在您的代碼中,您正在調用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.

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