C# 无法访问已释放的对象-wcf客户端

C# 无法访问已释放的对象-wcf客户端,c#,wcf-client,objectdisposedexception,C#,Wcf Client,Objectdisposedexception,我有一个WCF客户端遇到问题。 我不时会遇到这样的异常:无法访问已处理的对象。以下是我打开连接的方式: private static LeverateCrmServiceClient crm = null; public static CrmServiceClient Get(string crmCertificateName) { if (crm != null) { crm.Close();

我有一个WCF客户端遇到问题。
我不时会遇到这样的异常:
无法访问已处理的对象
。以下是我打开连接的方式:

private static LeverateCrmServiceClient crm = null;

public static CrmServiceClient Get(string crmCertificateName)
        {

            if (crm != null)
            {
                crm.Close();
            }
            try 
            {
                crm = new LeverateCrmServiceClient("CrmServiceEndpoint");
                crm.ClientCredentials.ClientCertificate.SetCertificate(
                               StoreLocation.LocalMachine,
                               StoreName.My,
                               X509FindType.FindBySubjectName,
                               crmCertificateName);
            }
            catch (Exception e) 
            {
                log.Error("Cannot access CRM ", e);
                throw;
            }
            return crm;
        }
如您所见,每次我都会关闭并重新打开连接。 你认为可能有什么问题

堆栈:

System.ServiceModel.Security.MessageSecurityException: Message security verification failed. ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.ServiceModel.Security.SymmetricSecurityProtocol'.
  at System.ServiceModel.Channels.CommunicationObject.ThrowIfClosedOrNotOpen()
  at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
  --- End of inner exception stack trace ---

Server stack trace:
  at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
  at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
  at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
  at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
  at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
  at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
  at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
  at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
  at Externals.CrmService.ICrmService.GetTradingPlatformAccountDetails(Guid ownerUserId, String organizationName, String businessUnitName, Guid tradingPlatformAccountId)
  at MyAppName.Models.ActionsMetadata.Trader.BuildTrader(Guid tradingPlatformAccountId) in C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata\Trader.cs:line 120
  at MyAppName.Models.ActionsMetadata.Trader.Login(String accountNumber, String password) in C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata\Trader.cs:line 48
  at MyAppName.Models.ActionsMetadata.Handlers.LoginHandler.Handle(StepHandlerWrapper wrapper) in C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata\Handlers\LoginHandler.cs:line 23
  at MyAppName.Models.ActionsMetadata.Handlers.HandlerInvoker.Invoke(IAction brokerAction, ActionStep actionStep, Dictionary`2 stepValues, HttpContext httpContext, BaseStepDataModel model) in C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata\Handlers\StepServerInoker.cs:line 42
  at MyAppName.Controllers.LoginController.Login(String step) in C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Controllers\LoginController.cs:line 35
  at lambda_method(Closure , ControllerBase , Object[] )
  at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
  at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
  at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
  at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
  at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
  at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
System.ServiceModel.Security.MessageSecurityException:消息安全验证失败。-->System.ObjectDisposedException:无法访问已处置的对象。
对象名称:“System.ServiceModel.Security.SymmetricSecurityProtocol”。
在System.ServiceModel.Channels.CommunicationObject.ThrowIfClosedOrNotOpen()中
在System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(消息和消息、时间跨度超时、SecurityProtocolCorrelationState[]相关状态)中
---内部异常堆栈跟踪的结束---
服务器堆栈跟踪:
在System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(消息和消息、时间跨度超时、SecurityProtocolCorrelationState[]相关状态)中
位于System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(消息回复、SecurityProtocolCorrelationState correlationState、TimeSpan超时)
位于System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(消息消息,TimeSpan超时)
在System.ServiceModel.Channels.ServiceChannel.Call(字符串操作、布尔单向、ProxyOperationRuntime操作、对象[]输入、对象[]输出、时间跨度超时)
位于System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage方法调用,ProxyOperationRuntime操作)
位于System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage消息)
在[0]处重试异常:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)
at System.Runtime.Remoting.proxy.RealProxy.PrivateInvoke(MessageData&msgData,Int32类型)
位于Externals.CrmService.ICrmService.GetTradingPlatformAccountDetails(Guid所有者序列号、字符串组织名称、字符串businessUnitName、Guid tradingPlatformAccountId)
在C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata.Trader.BuildTrader(Guid tradingPlatformAccountId)中的MyAppName.Models.ActionsMetadata.Trader(Guid tradingPlatformAccountId):第120行
在C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata.Trader.Login中的MyAppName.Models.ActionsMetadata.Trader.Login(字符串帐号,字符串密码):第48行
在C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata\Handlers\LoginHandler.Handler(StepHandlerWrapper包装器)中的MyAppName.Models.ActionsMetadata.Handlers.LoginHandler(StepHandlerWrapper包装器):第23行
在C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Models\ActionsMetadata\HandlerInvoker.Invoke中的MyAppName.Models.ActionsMetadata.HandlerInvoker.Invoke(IAction brokerAction,ActionStep ActionStep,Dictionary`2 stepValues,HttpContext,BaseStepDataModel)中:第42行
在C:\Users\X\Documents\Visual Studio 2010\Projects\MyAppName\MyAppName\Controllers\LoginController.Login中的MyAppName.Controllers.Login(字符串步骤):第35行
在lambda_方法中(闭包、控制器基、对象[])
位于System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext ControllerContext,IDictionary`2参数)
位于System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext ControllerContext,ActionDescriptor ActionDescriptor,IDictionary`2参数)
在System.Web.Mvc.ControllerActionInvoker.c_uuDisplayClass15.b_uuu12()中
位于System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter筛选器、ActionExecutingContext预文本、Func`1 continuation)
位于System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext ControllerContext,IList`1筛选器,ActionDescriptor ActionDescriptor,IDictionary`2参数)
位于System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext ControllerContext,String actionName)

根据堆栈跟踪,我假设您有一个ASP.NET MVC应用程序,其中的一些代码调用
Get
方法来获取
CrmServiceClient
对象,然后继续调用该
CrmServiceClient
对象上的各种方法。例如,登录过程的一部分就是这样做的

您的
Get
方法的工作方式是,每次调用它时,它将首先关闭它以前返回的
CrmServiceClient
对象(不管它是否仍在使用),然后创建并返回一个新对象

想象一下,两个用户几乎同时尝试登录到您的应用程序——彼此之间的间隔仅为毫秒。处理第一个用户登录的线程调用
Get
并获取其
CrmServiceClient
对象,然后一毫秒后处理第二个用户登录调用的线程调用
Get
,这导致第一个线程的
CrmServiceClient
对象关闭。但是,第一个线程仍在运行,现在当它尝试调用它的
CrmServiceClient
对象上的方法时,它会得到一个
System.ObjectDisposedException:无法访问已处置的对象

如您所见,每次我都会关闭并重新打开连接

当前在
Get
方法中的代码不是实现这一点的好方法。相反,您应该让调用方负责关闭(或处置)
CrmServiceClient
对象,您可能应该将
Get
方法重命名为
Open
Create
,以建议这样做。调用者应使用
using
语句来确保对象已关闭/释放,而不管发生任何异常:

using (CrmServiceClient client = CrmServiceFactory.Get("my-crm-certificate"))
{
    client.Something();
    client.GetTradingPlatformAccountDetails();
    client.SomethingElse();
} // client is automatically closed at the end of the 'using' block

这似乎已经在这里得到了回答:Per:“C#“using”语句导致调用