Exception within Parallel.Foreach

1,054 views
Skip to first unread message

e36M3

unread,
Apr 26, 2011, 3:50:58 PM4/26/11
to ninject
System.AggregateException: One or more errors occurred. --->
System.Reflection.TargetInvocationException: Exception has been thrown
by the target of an invocation. ---> System.IndexOutOfRangeException:
Index was outside the bounds of the array.
at System.Collections.Generic.List`1.Add(T item)
at Ninject.KernelBase..ctor(IComponentContainer components,
INinjectSettings settings, INinjectModule[] modules)


I never have an issue with this particular line of code, however today
I somehow managed to get into this state where I would get this
exception every time I attempted to run this line of code. I then
rebooted the server and everything worked flawlessly again. I am
constantly testing this Parallel.Foreach with 2000 items in the
collection.

Does anyone know why Ninject might throw this exception? BTW, I only
included the top level AggregateException to drive the point home that
it happened within Parallel.Foreach.

Thanks.

Remo Gloor

unread,
Apr 27, 2011, 4:21:34 AM4/27/11
to ninject
Hi

From the excpetion it seems that the error occurs in the constructor
of Ninject. This seems a little bit strange. Are you really creating
new kernel instances in the for each? Can you give more info about
what you are doing?

- Remo

e36M3

unread,
Apr 27, 2011, 9:43:04 AM4/27/11
to ninject
Here is my setup. First I am using a Unit Of Work implementation that
I got from some posts here. To be honest I don't have a deep enough
understanding of Ninject to say that it's solid, but it most
definitely seem to work. I am somewhat concerned about a potential
for memory leak, however my understanding/assumption that as long as I
use this within a "using" statement everything created by Ninject
within that objects scope should be disposed. Long story short I have
a few thousand objects which I want to process using
Parallel.Foreach. Each iteration within the parallel loop will create
an instance of several classes that inherit from the below
"SomeHelper" class. This means that each object has a fresh instance
of the IKernel. The reason I did it this way is because the entity
framework context is not thread safe (referenced below as
EFEntities). So my requirement was to make sure that each thread
operated on a fresh instance of the context. That said, I needed
multiple business layer classes to be created under the Validate()
method which would all internally share the same entity framework
object context to orchestrate a transaction so to speak.

Although the code does work as expected, and every thread gets proper
distribution of the entity framework context (I verified via
debugging) the memory usage is through the roof. The more concerning
part is that when all this code completes, I don't see the memory
being collected, so if I run it again it simply piles on top. There
might be more than one issue here, but you wanted some context :)

public class NinjectUnitOfWorkConfigModule : NinjectModule
{
public override void Load()
{

Bind(typeof(IGenericRepository<>)).To(typeof(GenericRepository<>)).InTransientScope();
//*** OTHER REPOSITORIES ***

//each using block gets a new NinjectUnitOfWork, diposed at the end
of the using block
Bind<NinjectUnitOfWork>().ToMethod(x => new
NinjectUnitOfWork(x.Kernel)).InThreadScope();

//each request gets the same ObjectContext within the
current NinjectUnitOfWork. Made available
//for GC when the using block ends
Bind<EFEntities>().ToMethod(x => new
EFEntities()).InUnitOfWorkScope();
}
}

public class NinjectUnitOfWork : ActivationBlock
{
public NinjectUnitOfWork(IResolutionRoot parent) :
base(parent)
{}

public override IRequest CreateRequest(Type service,
Func<IBindingMetadata, bool> constraint, IEnumerable<IParameter>
parameters, bool
isOptional, bool isUnique)
{
return Parent.CreateRequest(service, constraint,
parameters, isOptional, isUnique);
}

}

public static class NinjectExtensions
{
public static IBindingNamedWithOrOnSyntax<T>
InUnitOfWorkScope<T>(this IBindingWhenInNamedWithOrOnSyntax<T> self)
{
return self.InScope(x =>
self.Kernel.Get<NinjectUnitOfWork>());
}

}

public class NinjectInstance
{
public IKernel Kernel { get; private set; }

public NinjectInstance()
{
Kernel = new StandardKernel(new NinjectSettings()
{ AllowNullInjection = true } , new
NinjectUnitOfWorkConfigModule());
}
}

abstract class SomeHandler
{
//ninject instance
protected NinjectInstance ninjectInstance = new
NinjectInstance();

public virtual bool Execute()
{
LogValidationStart();

using (var unitOfWork =
ninjectInstance.Kernel.Get<NinjectUnitOfWork>())
{
Validate();
}

LogValidationEnd();

return true;
}

protected abstract bool Validate();

e36M3

unread,
Apr 27, 2011, 5:13:45 PM4/27/11
to ninject
I actually solved the memory usage issue by disposing of the IKernel
in every object after I am done with it. You can see the usage of
IDisposable around the NinjectInstance class, that solved all the
problems. To be completely honest I still don't understand why
calling Dispose() on the IKernel in every instance solved the
problem. My understanding that even if I didn't call Dispose() that
once the object that holds the reference to the IKernel goes out of
scope it should be eligible for garbage collection and eventually
collected. However I found that not to be the case. I wrote a loop
that would run my main() method a few times and between each iteration
it would call GC.Collect(), although some collection would occur the
memory usage clearly kept on climbing. Of course like I said if I
actually do call Dispose() myself then everything is fine. I must be
missing something. Of course none of this answers the original
question of why the Ninject constructor threw an exception that one
time.

public class NinjectInstance : IDisposable
{
public IKernel Kernel { get; private set; }

public NinjectInstance()
{
Kernel = new StandardKernel(new NinjectSettings()
{ AllowNullInjection = true } , new
NinjectUnitOfWorkConfigModule());
}

public void Dispose()
{
if (Kernel != null)
{
Kernel.Dispose();
}
}
}

abstract class SomeHandler
{
//ninject instance
protected NinjectInstance ninjectInstance;

public virtual bool Execute()
{
LogValidationStart();

using(ninjectInstance = new NinjectInstance())
{
using (var unitOfWork =
ninjectInstance.Kernel.Get<NinjectUnitOfWork>())
{
Validate();
}
}

LogValidationEnd();

return true;
}

protected abstract bool Validate();
}

e36M3

unread,
Apr 28, 2011, 10:33:46 AM4/28/11
to ninject
Interesting, like I stated before the memory issues has been solved,
so I decided to push the code back out to my VPS and test some there,
and I got another exception from Ninject! Just to be clear the
Parallel.Foreach is working perfectly fine on my laptop I7/Windows7
but as you can see I am seeing exceptions on my VPS that runs Windows
2008. Looks like it's now coming from Dispose() as opposed to
constructor. You can see from both exceptions that it's an issue
operating on a Generic List, almost like a threading issue within
Ninject?! I am not sure how that's possible especially being that I'm
creating a new instance of the StandardKernel per object.

System.AggregateException: One or more errors occurred. --->
System.ArgumentOutOfRangeException: Index was out of range. Must be
non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.Generic.List`1.RemoveAt(Int32 index)
at Ninject.KernelBase.Dispose(Boolean disposing)

Remo Gloor

unread,
Apr 28, 2011, 11:58:33 AM4/28/11
to nin...@googlegroups.com
Ctor is not threadsafe because of the OnePerRequestModule registration. But honestly what the hell are you doing here? I wonder that you don't have more problems as there are so many things that can go wrong with this implementation. E.g. accessing already disposed objects. I think you should have a look at https://github.com/ninject/ninject.extensions.namedscope/wiki.

e36M3

unread,
Apr 28, 2011, 12:48:38 PM4/28/11
to ninject
What are the issues that you see with this? I am simply using a
UnitOfWork implementation to allow all objects created within that UOF
to receive the same Entity Framework context. Are you saying it's not
good practice to create many instances of the Kernel, and I should be
sharing the same Kernel?

Thank you.

e36M3

unread,
Apr 28, 2011, 12:51:16 PM4/28/11
to ninject
Also forgot to ask where do you see any kind of OnePerRequestModule
declaration? I am not necessarily using this in a Web environment,
this is simply a library that can be executed from a command line
application for example.

Jeffrey Cameron

unread,
Apr 28, 2011, 7:22:12 PM4/28/11
to nin...@googlegroups.com
Hi e36me,

There should typically only be one instance of the IKernel object and this IKernel object should be used to inject long-lived singleton-type classes.  It is a design smell to have multiple instances of IKernel because it is more like using a Service Locator and not a Dependency Injection framework.  If you need multiple instances of UnitOfWork you might want to write a UnitOfWorkFactory object for this and use that, or use the scopes 

A good implementation of UnitOfWork can be found in the NCommon project (https://github.com/riteshrao/ncommon) which includes an implementation of UnitOfWork for Entity Framework as well.  NCommon has a Ninject adapter so that you can continue to use it with Ninject.  You'll see with that library that you usually do something like this

var kernel = new StandardKernel(blah blah);
var repository = kernel.Get<IRepository>();

using (var scope = new UnitOfWorkScope())
{
    // do your repository stuff here
    repository.GetAll();
}

Notice that NCommon uses the kernel to get the IRepository, the UnitOfWork is handled nicely with a separate scope.  Maybe this is more along the lines of what you might want to use?

--
You received this message because you are subscribed to the Google Groups "ninject" group.
To post to this group, send email to nin...@googlegroups.com.
To unsubscribe from this group, send email to ninject+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/ninject?hl=en.


Remo Gloor

unread,
Apr 28, 2011, 8:19:03 PM4/28/11
to ninject
1. OnePerRequest is a class of Ninject. The current implementation
makes ctor not threadsafe. The no web build does not have this
problem.
2. Creating a new Kernel for every single request: See Jeffs answer +
The same can be achieved much simpler using the scopes from the linked
extension of my previous post. I think it has been succested to you at
the time you asked here some months ago. I did never understand why
you created your own complicated infrastructure to do a simple task
for which all is already there.
3. If creating a new instance of the kernel then why not simply use
InSingletonScope?
4. If you are reusing the kernel instance. Are you aware that the UoW
is reused within the same thread forever? And that this results in
reusing a disposed object in the second using block? And that this
results in not releasing the objects created in the 2nd using?
Resulting in returning the objects from the 2nd in the 3rd and later
using? If you do not understand this part you should defenately not
use your implemetation as you do not understand its impact entirely.

e36M3

unread,
Apr 29, 2011, 8:16:21 AM4/29/11
to ninject
Remo, I very much appreciate your help. I really wish there was a
book out there on Ninject, for those of us that are not proficient
with DI in general. As a noob it's very difficult to pick this all up
without multiple detailed examples for every scope. If there was a
book, I'd be the first in line to buy it. Please bear with me, I
really want to understand and get this right.

I'll comment/ask based on the points you made in 1-4.

1. Fair enough, what is the "no web build" and when should it be
used? The Ninject.dll that I use is the one I got from going to the
main site and downloading the .NET 4.0 version. I don't believe it
states anywhere if it's "web" or "no web" build.

2. In my web projects I do only have one static instance of IKernel
(inside a singleton object) that I use to create my services, so I
never have a problem there. I do have a problem in my non-web
projects, because I can no longer define
Bind<EntityFrameworkContext>.ToSel().InRequestScope, obviously because
there is no request. I also don't want to use .InThreadScope because
in a Windows Service (file watcher) the same thread from the pool can
come back to process another file, therefore get the same
EntityFrameworkContext. In fact I really don't understand the purpose
(or usefulness) of InThreadScope, maybe it's not to be used with the
Thread Pool?

(I will be creating a new thread in regard to attempting to understand
how NamedScope extension can solve my problem, just so the threads are
somewhat on topic.)

3. I will try my best to understand how to solve my issues without
having more than 1 IKernel (my singleton) in the project.

4. I see what you're saying, is this because of the InThreadScope
here?
Bind<NinjectUnitOfWork>().ToMethod(x => new
NinjectUnitOfWork(x.Kernel)).InThreadScope();

What if I was to change this to:
Bind<NinjectUnitOfWork>().ToMethod(x => new
NinjectUnitOfWork(x.Kernel)).InTransientScope();

My understanding is that this will create a new NinjectUnitOfWork
every time a new "using" statement is used without any relation to any
thread. Since Ninject won't hold a reference to it, and it will be
going out of scope when the filewatcher event completes, isn't it
eligible for GC at that point? What do you think?

Thank you.

Remo Gloor

unread,
Apr 29, 2011, 9:30:06 AM4/29/11
to nin...@googlegroups.com
1. http://www.ninject.org/download see no web applications
    or https://github.com/ninject/ninject/downloads see no web
2. InThreadScope is for ThreadPool usage. e.g. you want to have several job processors on different threads. E.g a web server that processes each request on a different thread will create a processing engine in thread scope. It is created exactly once fo the thread and reused for each request that is processed on this thread.
3/4. If it was that easy I would have given you a solution. But it is not. As I said see the other scope types. They provide exactly what you need.

e36M3

unread,
Apr 29, 2011, 9:38:07 AM4/29/11
to ninject
Thanks Again Remo, I'm the process of looking at those extensions to
attempt to wrap my head around them. Quick question, is there
somewhere a description for the differences between the Web and NoWeb
versions? Currently I have a top level "Lib" folder with Ninject.dll
that I reference in all of my projects in the solution, some are web
and some are not. I wonder if it's an issue or not. I use Ninject
exactly the same (via a singleton that holds IKernel) whether it's web
or not, in other words I don't use any of the Web specific extensions
or attributes. The only thing that changes are the scopes of the
bindings. Would the non-web version be sufficient (if it supports
InRequest scope)?

On Apr 29, 9:30 am, Remo Gloor <remo.gl...@bbv.ch> wrote:
> 1.http://www.ninject.org/downloadsee no web applications
>     orhttps://github.com/ninject/ninject/downloadssee no web

Remo Gloor

unread,
Apr 29, 2011, 10:11:13 AM4/29/11
to nin...@googlegroups.com
NoWeb has no InRequestScope and no OnePerRequestModule

e36M3

unread,
Apr 29, 2011, 10:13:20 AM4/29/11
to ninject
Understood, what does NoWeb offer that the Web does not? You've
already mentioned that the constructor is thread safe. Assuming that
there is only one instance of the IKernel in my application, does the
NoWeb provide me any benefit?

Thank you.

Remo Gloor

unread,
Apr 29, 2011, 10:17:02 AM4/29/11
to nin...@googlegroups.com
NoWeb is just a subset to support Apps in client profile

e36M3

unread,
Apr 29, 2011, 10:23:46 AM4/29/11
to ninject
Perfect. Thank you very much.
Reply all
Reply to author
Forward
0 new messages