Intermittent LifetimeScope error: SelfRegistrationCannotBeActivated

514 Views Asked by At

I have a scenario which involves a separate LifetimeScope per "session" and long-running resolve in worker thread. I am getting an erratic error which may have something with timing - it happens when lifetime scopes are disposed / created before the actual resolution had a chance to finish.

I am kind of clueless since the exception is a bit cryptic - few layers of nested DependencyResolutionException and InvalidOperationException with the following message at the bottom: "The container's self-registration of context interfaces should never be activated as it is hard-wired into the LifetimeScope class. "

The Autofact code that throws it doesn't reveal much as well -> https://github.com/autofac/Autofac/blob/d44e09d37863e13aa09eefa6f249caf1e5caf0f1/src/Autofac/Core/Container.cs

In what conditions is this exception thrown actually?

1

There are 1 best solutions below

0
On BEST ANSWER

If you have a multithreaded scenario where you're doing resolution on a separate thread (which is what you describe) then you're going to have to do a lot of locking around lifetime scope creation and disposal. Disposing a lifetime scope whilst trying to resolve something from that lifetime scope is going to get you into a world of trouble. The result of that is you'll see weird messages that don't make a lot of sense.

Actually walking back through the code to figure out all the ways you can get to this error will likely lead to one (or more) of these results:

  • It's going to take a lot of time.
  • It's going to be really confusing and difficult to decipher what you find.
  • It's not going to matter much in the end because the solution is going to be really careful with locks, multithreading, and scope creation/disposal.

By way of example, Autofac had a long running issue for a while where disposing a parent lifetime scope does not dispose of any child scopes that were spawned from that parent. We worked on a fix for it for a long while, but it turned out that by tracking the hierarchy of scopes that way it would very easily introduce memory leaks in high traffic like web sites where there's a lifetime scope per request. The end result was wontfix because if you're spinning up lifetime scopes, you should be very responsible about tearing them down, too.

By and large, resolve operations are a lot like constructors - they should be very fast, atomic, and not require multithreading. Once you get into having to spawn a worker thread to perform a resolve that takes a long time... that's more an architectural issue to solve.