2012-04-04 73 views
4

我有一个WCF客户端,我遇到了问题。
我不时得到这个例外:Cannot access a disposed object。这是我如何打开连接:无法访问处置对象 - 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) 
+0

这似乎已经在这里answerwed:http://stackoverflow.com/questions/4573526/what -could待引起-A-不能存取A-设置对象误差合WCF – Chriseyre2000 2012-04-04 12:05:10

回答

6

从这个堆栈跟踪,我假设你有一些代码,调用Get方法得到一个CrmServiceClient对象,然后继续上调用各种方法ASP.NET MVC应用程序即CrmServiceClient对象。例如,部分登录过程执行此操作。

Get方法的工作原理是这样的,每次被调用时,它会首先关闭CrmServiceClient对象,它以前返回(无论是否仍在使用它),然后创建并返回一个新的。

想象一下两个用户试图登录到您的应用程序几乎在同一时间 - 彼此毫秒内。线程处理完第一个用户的登录调用Get并获得其CrmServiceClient对象,然后一毫秒后,线程处理所述用户的登录调用Get,这导致第一线程的CrmServiceClient对象被关闭。但是,第一个线程仍在运行,现在当它尝试调用对象CrmServiceClient上的方法时,它会得到一个System.ObjectDisposedException: Cannot access a disposed object

“正如您所看到的,我每次关闭并重新打开连接。”

当前在您的Get方法中的代码不是实现此目的的好方法。而应该让调用者负责关闭(或处置)的CrmServiceClient对象,你应该将Get方法可能重命名为OpenCreate表明这一点。调用者应该使用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