ObjectDisposedException

ObjectDisposedException

Old forum URL: forums.lhotka.net/forums/t/11839.aspx


rfcdejong posted on Friday, February 15, 2013

This could just be in debug with exception's on, but i wonder if this might be a bug..

At ApplicationContext the GetLocalContext() method throws: "Cannot access a closed file"

 

It happens when the GC finalize an ObjectFactory which dispose the repository using a Csla.Data.EF5.DbContextManager which does a DeRef as being a IDisposable. It wants to remove the ContextLabel from the ApplicationContext.LocalContext.

Somehow the LocalDataStoreSlot is closed before the DbContextManager is being finalized.


PS: The backend - server side code - is hosted in IIS with Apppool recycling on. I think it happens when the Apppool is recycled.

It could be that i have to force a dispose the ContextManager after using it? But that might be a problem since the factory's are somehow a unit of work and while the unit of work is running the ContextManager must be up. There is no memory leak, the GC is just not disposing fast enough. The LocalDataStoreSlot is just gone.

rfcdejong replied on Tuesday, March 12, 2013

This is becomming a problem, the DbContextManager is being finalized after the NamedDataslot has been freed.

The InvalidOperationException with message "LocalDataStoreSlot storage has been freed" is being thrown whenever the GC comes by to dispose the DbContextManager.

Since we are not using code that forces to dispose after usage, can it be made a bit safer? Maybe a check if the context hasn't been disposed before accessing it?

Our code:
The root factory creates have a IRepository injected.
The classes implementing IRepository create a DbContextManager in the constructor and implementing IDisposable they dispose the DbContextManager when all the factory's holding a reference to the repository are disposed.

In the DeRef the RefCount get to 0 and then it want to execute the following code resulting into the exception.

 

    private void DeRef()
    {
 
      lock (_lock)
       {
        _refCount -= 1;
        if (_refCount == 0)
        {
          _context.Dispose();
          ApplicationContext.LocalContext.Remove(ContextLabel);
        }
      }
    }

RockfordLhotka replied on Tuesday, March 12, 2013

LocalContext is stored in thread local storage. So you are saying that the thread is gone before all the using blocks have been exited?

I guess I'm not understanding the scenario you are describing...

rfcdejong replied on Wednesday, March 13, 2013

We aren't using 'using blocks'. The thread and later on the GC comes by, something like that.

The exception takes a time to happen, the thread is not directly gone, we also don't force the GC to collect.

RockfordLhotka replied on Wednesday, March 13, 2013

The data object context objects in Csla.Data are _designed_ for using blocks. The entire point of these types is to do reference counting so the underlying objects are disposed appropriately.

If you aren't either using a using block or manually calling dispose on the context object I would _expect_ there to be problems. That's not a bug, that's the way these types are designed to function.

Copyright (c) Marimer LLC