Исключение исключений в Parallel.Foreach - PullRequest
7 голосов
/ 28 апреля 2011

У меня есть фрагмент кода, который запускает Parallel.Foreach в списке элементов для обработки.Каждая итерация создает пару объектов, каждый из которых создает и реализует свой экземпляр Ninject IKernel.IKernel утилизируется, когда объект готов к работе.

Тем не менее, этот код прекрасно работает на моем ноутбуке с Windows 7, I7.Однако когда я отправляю его на свой VPS, который работает под управлением Windows 2008, я получаю это исключениеИсключение не происходит на одной и той же итерации, иногда оно проходит через 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 для одного приложения.Это вопрос понимания того, как настроить надлежащие области для обеспечения безопасности потоков контекста Entity Framework, сохраняя при этом подход типа UoW, при котором несколько классов бизнес-уровня могут совместно использовать один и тот же контекст EF в пределах области UoW в одном потоке.

Ответы [ 2 ]

5 голосов
/ 29 апреля 2011

См. http://groups.google.com/group/ninject/browse_thread/thread/574cd317d609e764

Как я уже говорил, ctor Ninject не является потокобезопасным, если вы не используете NOWEB!Если вы создаете / удаляете ядро ​​столько раз, вам придется синхронизировать доступ самостоятельно!Я все еще предлагаю изменить вашу реализацию UoW!

0 голосов
/ 28 апреля 2011

Кажется, что ninjectInstance является переменной экземпляра.Следовательно, возможно, что в параллельной среде ninjectInstance.Dispose() будет вызываться дважды (вызов Kernel.Dispose() не устанавливает для свойства ядра значение null ) для того же экземпляра, и поскольку Kernel.Dispose() уже вызван, метод не работает.

Может быть, вы хотели что-то вроде

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