2012-04-04 41 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