This project is read-only.

WCF Web Service - Slow starting caused by SimpleInjector

Feb 13, 2014 at 10:56 PM
I have a large webservice project which exposes a number of WCF operations to clients.

DI is configured to run during app_start, from the global asax.

I've noticed a FLOOD of
A first chance exception of type 'System.InvalidOperationException' occurred in SimpleInjector.dll
A first chance exception of type 'System.InvalidOperationException' occurred in SimpleInjector.Extensions.LifetimeScoping.dll
A first chance exception of type 'System.InvalidOperationException' occurred in SimpleInjector.dll
A first chance exception of type 'System.InvalidOperationException' occurred in SimpleInjector.Integration.Wcf.dll
in the debug output window for visual studio. Hundreds of lines. This exception throwing and suppressing is causing around a 30 second delay during the start of the service. While functionally everything is working, I'd really like to know whats going on here and if I can reduce this lag.

I attached to the AppDomain.FirstChanceException event to get more details about these exceptions:
2014-02-13 15:32:22,817 [5512] DEBUG Service.Bootstrapper [(null)] - System.InvalidOperationException: The container can't be changed after the first call to GetInstance, GetAllInstances and Verify.
   at SimpleInjector.Container.ThrowWhenContainerIsLocked()
2014-02-13 15:32:22,839 [5512] DEBUG Service.Bootstrapper [(null)] - System.InvalidOperationException: The container can't be changed after the first call to GetInstance, GetAllInstances and Verify.
   at SimpleInjector.Container.ThrowWhenContainerIsLocked()
   at SimpleInjector.Container.AddRegistration(Type serviceType, Registration registration)
   at SimpleInjector.Container.RegisterSingle[TService](TService instance)
   at SimpleInjector.SimpleInjectorLifetimeScopeExtensions.EnableLifetimeScoping(Container container)
2014-02-13 15:32:22,883 [5512] DEBUG Service.Bootstrapper [(null)] - System.InvalidOperationException: The container can't be changed after the first call to GetInstance, GetAllInstances and Verify.
   at SimpleInjector.Container.ThrowWhenContainerIsLocked()
2014-02-13 15:32:22,912 [5512] DEBUG Service.Bootstrapper [(null)] - System.InvalidOperationException: The container can't be changed after the first call to GetInstance, GetAllInstances and Verify.
   at SimpleInjector.Container.ThrowWhenContainerIsLocked()
   at SimpleInjector.Container.AddRegistration(Type serviceType, Registration registration)
   at SimpleInjector.Container.RegisterSingle[TService](TService instance)
   at SimpleInjector.SimpleInjectorWcfExtensions.EnablePerWcfOperationLifestyle(Container container)
After the Verify() call is finished, these messages stop.

Why is Verify side-effecting, by attempting to register some things? Especially since it's in a locked state?
Feb 14, 2014 at 6:58 AM
Which version of Simple Injector are you using?
Feb 15, 2014 at 12:02 AM
SimpleInjector.dll : 2.3.0.0
SimpleInjector.Extensions.LifetimeScoping.dll : 2.3.1.0
Feb 15, 2014 at 7:07 AM
Could you please upgrade to the latest version (2.4.1) and try again? We are constantly improving performance of the feamework and should see a lot less of these first chance exceptions with the latest version.
Feb 18, 2014 at 5:27 PM
2.4.1 appears to be better, but the problem is not completely resolved.

During verify, InvalidOperationException was thrown 468 times using 2.3.0
During verify, InvalidOperationException was thrown 237 times using 2.4.1
Feb 18, 2014 at 6:10 PM
I'm sorry, I haven't been paying attention to the last part of your initial question. My first impression was that the exceptions where caused by the registration of generic types using generic type constraints (Simple Injector 2.4.1. has an optimization which ensures much less of those exceptions are thrown). But the list below shows that the exceptions originate from the EnableLifetimeScoping and EnablePerWcfOperationLifestyle methods.

This is in fact a problem that has already been fixed in the trunk. You can confirm this by testing this using Simple Injector 2.5.0-beta1 (also include the LifetimeScope and Integration.Wcf packages).

What you're experiencing is the initialization of those two lifestyles. Every time a new Registration is created by those lifestyles, they will call their EnableXXX method. This method tries to register the manager class as singleton in the container. The manager class controls the creation of new scopes for a container instance. The manager however, can't be registered if the container's already locked. The container will throw an exception in that case, but it's okay to dismiss this exception.

In Simple Injector 2.5, the lifestyles are refactored in such way that this manager doesn't have to be registered in the container anymore. That has removed the need for those lifestyles to enable the lifestyle (and removes the need for a user to call container.EnableLifetimeScope manually). Instead of registering the manager in the container, the lifestyles make use of the container's Items dictionary (a dictionary that's much like the ASP.NET HttpContext.Items dictionary). This will prevent any exceptions from being thrown.

I expect 2.5 to be released within a couple of weeks, so hopefully you can wait for it to be released. If that's a problem, the beta1 release is of very high quality and can IMO be safely used in production. Do note that there will be some breaking changes between beta1 and 2.5 RTM, but those changes will be concentrates around the SimpleInjector.ScopedLifestyle class. Unless you're writing a custom lifestyle (or mixing beta1 extension/integration packages with RTM code library) you'd be safe.
Marked as answer by dot_NET_Junkie on 2/26/2014 at 11:26 AM
Feb 19, 2014 at 9:32 PM
Thanks for keeping up with this.

I may give the beta a try, but I'll wait for it to be released before I check in code using it.
Mar 14, 2014 at 12:34 AM
Update: We've updated to Simple Injector 2.5 and the number of first-chance exceptions has plummeted down to an acceptable 5! Fantastic.
Mar 14, 2014 at 7:21 AM
Good to hear. I'm interested to know what exceptions are still thrown. Can you post the appropriate information about this? So type, message and stack trace. Thanks
Mar 14, 2014 at 4:26 PM
You know what, apologies, I mistook a couple of .NET/WCF related ones for Simple Injector. There weren't any exceptions thrown from Simple Injector when I looked a little closer. I debugged through the bootstrap process and nothing but assembly loads were reported.