System.ObjectDisposedException: 'Cannot access a disposed object. while using ISession.connect
Hi Team,
We are incorporating Solace in our .Net core API and trying to create session object in one cs file and adding it to a property in another cs file where I am using session.Connect(). When we try to connect to session it is showing an exception "that object is disposed". Below is code for your reference.
=========================================================================
public static ISession GetSolacecConnection(SolaceConnectionRequest solaceConnectionRequest) { //Initialize Solace Systems Messaging API with logging to console at Warning level ContextFactoryProperties cfp = new ContextFactoryProperties() { SolClientLogLevel = SolLogLevel.Warning }; cfp.LogToConsoleError(); ContextFactory.Instance.Init(cfp); try { using (IContext context = ContextFactory.Instance.CreateContext(new ContextProperties(), null)) { // Validate parameters if (context == null) { throw new ArgumentException("Solace Systems API context Router must be not null.", "context"); } if (string.IsNullOrWhiteSpace(solaceConnectionRequest.Host)) { throw new ArgumentException("Solace Messaging Router host name must be non-empty.", "host"); } if (string.IsNullOrWhiteSpace(solaceConnectionRequest.VpnName)) { throw new InvalidOperationException("VPN name must be non-empty."); } if (string.IsNullOrWhiteSpace(solaceConnectionRequest.UserName)) { throw new InvalidOperationException("Client username must be non-empty."); } cfp.LogToConsoleError(); //We can log it to a file later ContextFactory.Instance.Init(cfp); var sessionProps = GetSessionProperties(solaceConnectionRequest.Host, solaceConnectionRequest.VpnName, solaceConnectionRequest.UserName, solaceConnectionRequest.Password, solaceConnectionRequest.DefaultReconnectRetries); ISession session = context.CreateSession(sessionProps, null, HandleSessionEvent); if (session != null) { //ReturnCode returnCode = session.Connect(); //return returnCode; return session; } } return null; } catch (Exception ex) { return null; } }
=======================================================================
private readonly ISession _session; public async Task Run(SolaceRequest solaceRequest) { try { if (_session != null) { ReturnCode returnCode = _session.Connect(); // failing while connecting if (returnCode == ReturnCode.SOLCLIENT_OK) { _logger.LogInformation("Session successfully connected."); await SendMessage(_session, solaceRequest); _logger.LogInformation("Waiting for a message to be published..."); } else { _logger.LogError("Error connecting, return code: {0}", returnCode); } } } catch (Exception ex) { _logger.LogError("Exception thrown: {0}", ex.Message); } finally { // Dispose Solace Systems Messaging API //ContextFactory.Instance.Cleanup(); } _logger.LogInformation("Finished."); }
Answers
-
Greetings and welcome to the community!
This issue you are facing is because of the parent-child relationship between
IContext
andISession
. Within theGetSolaceConnection(...)
method, you create a context from the context factory, and then a session on that context; however, the context creation is performed within ausing
block, and as such, the context is disposed immediately before the method returns.So even though the session instance is not disposed, its underlying context has been; so calling
.Connect()
will generate anObjectDisposedException
with the following message:Cannot access a disposed object.
Object name: 'Cannot Connect an already disposed session'.
To remedy this, the lifecycle of the
IContext
andISession
instances should be more-or-less the same. If you have a global static class holding a reference toISession _session
, then you should likewise hold a reference to the context via a fieldIContext _context
to be safe.In short, for long-lived session variables, be sure both
ISession
andIContext
are not prematurely disposed within ausing
statement.1