I am following the example linked to below for setting up unity to work with my service layer. My project is setup very similar to the one in this article and I understand everything except why exactly is PerThreadLifetimeManager
used when registering the service dependency. Keep in mind I am also using a generic repository and unit of work that is being used in my service layer as well. Most unity examples use the default (transient) lifetime manager, and since my setup is similar to the one below I'm wondering why I should use the PerThreadLifeimeManager
? I am using an ASP.NET web forms project for my current presentation layer if that changes anything.
container.RegisterType<ICatalogService, CatalogService>(
new PerThreadLifetimeManager())
[The repository pattern with EF code first dependency injection in asp.net MVC 3][1] [1]: http://www.dotnetage.com/publishing/home/2011/07/05/6883/the-repository-pattern-with-ef-code-first-dependeny-injection-in-asp-net-mvc3.html
Use the ContainerControlledLifetimeManager when you want to create a singleton instance. In the above example, we specified ContainerControlledLifetimeManager in the RegisterType() method. So, Unity container will create a single instance of the BMW class and inject it in all the instances of Driver .
Per thread lifetime means a new instance of the registered Type will be created once per each thread. In other words, if a Resolve<T>() method is called on a thread the first time, it will return a new object.
RegisterType a type mapping with the container, where the created instances will use the given LifetimeManager. Namespace: Microsoft.Practices.Unity.
Per-Thread storage refers to the storage which is local to each thread in a parallel program. This can be very useful in certain multi-threaded scenarios. For example, consider a multi-threaded program which accumulates information into a global variable.
The Per Thread Lifetime is a very dangerous lifestyle and in general you should not use it in your application, especially web applications.
This lifestyle should be considered dangerous, because it is very hard to predict what the actual lifespan of a thread is. When you create and start a thread using new Thread().Start()
, you'll get a fresh block of thread-static memory, which means the container will create a new per-threaded instance for you. When starting threads from the thread pool using ThreadPool.QueueUserWorkItem
however, you get possibly an existing thread from the pool. The same holds when running in ASP.NET. ASP.NET pools threads to increase performance.
This means that a thread will almost always outlive a web request. ASP.NET on the other hand can run requests asynchronously, which means that a web request can be finished at a different thread. And this is a problem when working with a Per Thread lifestyle. And of course this effect is amplified when you start using async/await.
This is a problem since you will typically call Resolve<T>
once at the beginning of the request. This will load the complete object graph including your services that are registered with the Per Thread lifestyle. When ASP.NET finishes the request at a different thread, this means that the resolved object graph moves to this new thread, including all Per Thread registered instances.
Since these instances are registered as Per Thread, they are probably not suited to be used at another thread. They are almost certainly not thread-safe (otherwise they would be registered as Singleton). Since the first thread that initially started the request is already free to pick up new requests, you can run into the situation where two threads access those Per Thread instances simultaneously. This will lead to race conditions and bugs that are hard to diagnose and find.
So in general, using Per Thread is a bad idea. Instead use a lifestyle that has a clear scope (an implicit or explicitly defined begin and end). The Per Web Request lifestyle that most DI frameworks implement is often implicitly scoped (you don't have to end it yourself).
To make things worse, the blog post you referenced contains a configuration error. The ICatalogService
is defined with a Per Thread lifestyle. This service however depends on an IDALContext
service, which is defined as Transient. Since a reference to a IDALContext
instance is stored as private field inside the CatalogService
, this means the DALContext
lives as long as the ICatalogService
does. This is a problem because IDALContext
is defined as Transient and is probably not thread-safe.
The general rule is to let components only depend on services with an equal or longer lifetime. So a Transient can depend on a Singleton but not the other way around.
Since a Per Thread registered component will typically live very long, it can typically only safely depend on other Per Thread or Singleton instances. And since ASP.NET can split a single request up in multiple threads, it is not safe to use Per Thread in the context of a ASP.NET application (both MVC, Web Forms, and especially Web API).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With