简体   繁体   中英

The ObjectContext instance has been disposed - Is this thread safe?

I have a collection of System.Threading.Timer that run in the background of a webapp that periodically retrieve data from a DB to update the cache.

Occasionally (not often), calls to the DB will fail with an error such as "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection".

It seems like it's sometimes being disposed by another thread, but when each timer runs, it'll create a brand new DbContext, so I'm not sure how that can be the case.

I'm using StructureMap to create a nested container, so that it runs in isolation, and I've verified that it does indeed create a new DbContext for each timer.

var a = new A();
var b = new B();

var timer1 = new Timer(x => a.Update(container), null, TimeSpan.Zero, TimeSpan.FromMinutes(60));
var timer2 = new Timer(x => b.Update(container), null, TimeSpan.Zero, TimeSpan.FromMinutes(60));

public class A 
{
    public void Update(IContainer container)
    { 
        using (var nestedContainer = container.GetNestedContainer()) {
            // This will create a new DbContext and will be disposed 
            // when the nested container is disposed
            var repository = nestedContainer.GetInstance<IRepositoryA>();

            // Sometimes fails here when it's accessing the DbContext
            repository.GetStuff();
        }
    }
}

public class B
{
    public void Update(IContainer container)
    { 
        using (var nestedContainer = container.GetNestedContainer()) {
            var repository = nestedContainer.GetInstance<IRepositoryB>();

            repository.GetStuff();
        }
    }
}

Here's the StructureMap config. So whenever a repository is created it will create a new factory which in turn creates a new MyDbContext.

For<IDbContextFactory<MyDbContext>>().HybridHttpOrThreadLocalScoped()
    .Use(() => new DbContextFactory());

It turns out this was being caused by the HybridHttpOrThreadLocalScoped StructureMap plugin, which disposed of the DbContext when the local thread disposed of the nested container, so other threads could no longer use it. Removing that and changing my StructureMap config to use a nested container for the lifecycle of an HTTP request resolved it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM