Skip to content
alexmg edited this page Jan 22, 2014 · 1 revision

Use nested lifetime scopes to provide thread-specific binding

Autofac can enforce that objects bound to one thread will not satisfy the dependencies of a component bound to another thread. This is done using lifetime scopes:

var builder = new ContainerBuilder();
builder.RegisterType<MyThreadScopedComponent>()
  .InstancePerLifetimeScope();
var container = builder.Build();

Then, each thread gets its own inner context:

void ThreadStart()
{
  using (var threadLifetime = container.BeginLifetimeScope())
  {
    var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>();
  }
}

Important: Given the multithreaded scenario, you must be very careful that the parent scope doesn't get disposed out from under the spawned thread. You can get into a bad situation where components can't be resolved if you spawn the thread and then dispose the parent scope.

Each thread executing through ThreadStart() will then get its own instance of MyThreadScopedComponent - which is essentially a "singleton" in the lifetime scope. Because scoped instances are never provided to outer scopes, it is easier to keep thread components separated.

You can inject a parent lifetime scope into the code that spawns the thread by taking an ILifetimeScope parameter. Autofac knows to automatically inject the current lifetime scope and you can create a nested scope from that.

public class ThreadCreator
{
  private ILifetimeScope _parentScope;

  public ThreadCreator(ILifetimeScope parentScope)
  {
    this._parentScope = parentScope;
  }

  public void ThreadStart()
  {
    using (var threadLifetime = this._parentScope.BeginLifetimeScope())
    {
      var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>();
    }
  }
}

If you would like to enforce this even more heavily, use Tagged Contexts to associate the thread-scoped components with the inner lifetime (they'll still have dependencies from the factory/singleton components in the outer container injected.) The result of this approach looks something like:

http://autofac.googlecode.com/svn/site/threadedcontainers.png

The 'contexts' in the diagram are the containers created with BeginLifetimeScope().

Clone this wiki locally