Parallel.Foreach 中的 Ninject 异常

发布于 2024-11-04 02:04:18 字数 1595 浏览 1 评论 0原文

我有一段代码,它在要处理的项目列表上运行 Parallel.Foreach 。每次迭代都会创建几个对象,每个对象实例化并处理它自己的 Ninject IKernel 实例。当对象完成其工作时,IKernel 将被释放。

也就是说,这段代码在我的 Windows 7、I7 笔记本电脑上运行得非常好。但是,当我将其推送到运行 Windows 2008 的 VPS 时,出现此异常。异常不会在同一次迭代中发生,有时会经历 10 次迭代并抛出异常,有时会经历数百次迭代。显然,这似乎是一个线程问题,但除了我的 VPS 之外,其他任何地方都不会发生这种情况。如果重要的话,它托管在 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)

以下是代码片段:

//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();
        }
    }
}   

编辑 1 有一点是肯定的,这是一个线程安全问题,我不应该为每个应用程序创建多个 IKernel 实例。需要理解如何配置适当的范围以实现实体框架上下文线程安全,同时保留 UoW 类型方法,其中多个业务层类可以在单个线程内的 UoW 范围内共享相同的 EF 上下文。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

颜漓半夏 2024-11-11 02:04:18

请参阅 http://groups.google.com/group/ninject/browse_thread/thread /574cd317d609e764

正如我告诉你的,Ninject 的 ctor 不是线程安全的 atm,除非你使用 NOWEB!如果创建/处置内核多次,您将必须自己同步访问!我仍然建议重新设计你的 UoW 实施!

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!

山色无中 2024-11-11 02:04:18

看起来ninjectInstance是一个实例变量。因此,在并行环境中,ninjectInstance.Dispose() 可能会被调用两次(调用 Kernel.Dispose() 不会将 Kernel 属性设置为 null) 对于同一实例,并且由于已经调用了 Kernel.Dispose(),因此该方法失败。

也许你想要类似的东西

using (var ninjectInstance = new NinjectInstance()) {
..
}

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()) {
..
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文