我的系统中有两个WCF网络服务。
Web服务A调用Web服务B.大部分时间,它都能正常工作。但是,在调用B:
时,会引发A中的异常调用目标抛出了异常。
为了试着知道问题出在哪里,我在B中的被调用方法中放了一个巨大的Try Catch,从第一条指令到最后一条指令。同样的问题。
然后我尝试将customErrors设置为off并将includeExceptionDetailInFaults设置为true,以便从异常中获取详细信息。同样的问题。
这不是超时问题,因为请求持续时间低于1秒。
我检查了请求的长度,一些好的请求比不好的请求长。问题不在于规模。
我无法重现这个问题,因为它只出现了几次。
我认为如果问题出现在A上,则异常会比此消息有更多详细信息。
问题可能在IIS上(两者都在同一个IIS实例上),但A通过localhost:xxxx / mywebservice.svc与B通信,所以很难相信这是一个通信问题。
编辑:
有InnerException消息:
无法访问已处置的对象。对象名称: 'System.ServiceModel.Channels.ServiceChannel'。
网络服务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 []参数,SignatureStruct& SIG, MethodAttributes methodAttributes,RuntimeType typeOwner)at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo方法, Object target,Object []参数,Signature sig,MethodAttributes methodAttributes,RuntimeType typeOwner)at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder binder,Object []参数,CultureInfo文化, 布尔值skipVisibilityChecks)at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder binder,Object []参数,CultureInfo文化)
在System.RuntimeType.InvokeMember(String name,BindingFlags bindingFlags,Binder binder,Object target,Object [] providedArgs, ParameterModifier []修饰符,CultureInfo文化,String [] 在WS_Generic.Service.CallWsMethod(String。)中的namedParams sXmlSettings,String sXmlIN,String& sXmlOUT)
有一个完整的InnerException:
无法访问已处置的对象。对象名称: 'System.ServiceModel.Channels.ServiceChannel'。
服务器堆栈跟踪:at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen() 在System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway,ProxyOperationRuntime操作,Object [] ins, 对象[]出局,TimeSpan超时)at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime operation)at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(即时聊天 消息)
在[0]处重新抛出异常:at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(即时聊天 reqMsg,IMessage retMsg)at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&安培; IWsAfsol.EmvTrxAuthorization(String sXmlIn)中的msgData,Int32类型) 在WsAfsolClient.EmvTrxAuthorization(String sXmlIn)
答案 0 :(得分:0)
我在您的更新中快速使用了Google,并在asp.net论坛上找到了this post。
我猜测(不知道你的代码是什么样的)你有一个共享的连接/服务,你打开它然后在代码中需要时调用。
选项(再次,猜测这里没有看到代码)
根据您的最新修改进行修改:
在您的代码中,您正在调用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