Ninject exception in Parallel.Foreach
I have a piece of code that runs a Parallel.Foreach
on a list of items to process. Each iteration creates a couple of objects with each object instantiating and disposing it's own instance of the Ninject IKernel. The IKernel is disposed when the object is done it's work.
That said, this code works perfectly well on my Windows 7, I7 laptop. However when I push it out to my VPS that runs Windows 2008 I get this exception. The exception doesn't happen on the same iteration, sometimes it will get through 10 iterations and throw an exception, other times it will go through hundreds of them. Obviously seems like a threading issue, but it doesn't happen anywhere but my VPS. If it matters this is being hosted in ASP.NET IIS.
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)
Here is a snippet of the code:
//Code that creates and disposes the Ninject kernel
using(ninjectInstance = new NinjectInstance())
{
using (var unitOfWork = ninjectInstance.Kernel.Get<NinjectUnitOfWork>())
{
Init();
continueValidation = Validate(tran, ofr);
}
}
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();
}
}
}
Edit 1 One thing is for sure, this is a thread safety issue and I should not be creating more than one instance of IKernel per application. It's a matter of understanding on how to configure the proper scopes in order to accomplish Entity Framework Context thread safety yet preserving the UoW type approach where multiple business layer classes can share the same EF context within the UoW scope within a single thread.
See http://groups.google.com/group/ninject/browse_thread/thread/574cd317d609e764
As I told you Ninject's ctor is not threadsafe atm unless you are using NOWEB
! If creating/disposing the kernel so many times you will have to synchronize the access yourself! I still suggest to redesign your UoW implementation!
It seems like ninjectInstance
is an instance variable. Hence, it's possible that in a parallel environment, ninjectInstance.Dispose()
will be called twice (calling Kernel.Dispose()
does not set the Kernel property to null) for the same instance and since Kernel.Dispose()
is already been called, the method fails.
Maybe you wanted something like
using (var ninjectInstance = new NinjectInstance()) {
..
}
链接地址: http://www.djcxy.com/p/52250.html