Подтвердить что ты не робот

Когда использовать PerThreadLifetimeManager?

Я следую примеру, приведенному ниже, для настройки единства для работы со своим уровнем обслуживания. Мой проект настроен очень похоже на тот, который описан в этой статье, и я все понимаю, кроме того, почему именно PerThreadLifetimeManager используется при регистрации зависимости службы. Имейте в виду, что я также использую общий репозиторий и unitofwork, которые также используются в моем слое обслуживания. В большинстве примеров Unity используется менеджер времени жизни по умолчанию (временный), и, поскольку мои настройки аналогичны приведенным ниже, мне интересно, почему я должен использовать PerThreadLifeimeManager? Я использую проект веб-форм ASP.NET для моего текущего уровня представления, если это что-то меняет.

container.RegisterType<ICatalogService, CatalogService>(new PerThreadLifetimeManager())

Шаблон репозитория с внедрением первой зависимости кода EF в asp.net MVC 3

4b9b3361

Ответ 1

За нить Образ жизни считается вредным

Продолжительность жизни Per Thread - очень опасный образ жизни, и в целом вы должны не использовать его в своем приложении, особенно в веб-приложениях.

Этот образ жизни следует считать опасным, потому что очень сложно предсказать, какова фактическая продолжительность жизни нити. Когда вы создаете и запускаете поток с помощью new Thread().Start(), вы получите свежий блок потоко-статической памяти, а это означает, что контейнер создаст для вас новый экземпляр с несколькими потоками. При запуске потоков из пула потоков с помощью ThreadPool.QueueUserWorkItem, однако, вы получаете, возможно, существующий поток из пула. То же самое происходит при работе в ASP.NET. ASP.NET объединяет потоки для повышения производительности.

Это означает, что поток почти всегда переживает веб-запрос. ASP.NET, с другой стороны, может запускать запросы асинхронно, что означает, что веб-запрос может быть завершен в другом потоке. И это проблема при работе с образцом Per Thread. И, конечно, этот эффект усиливается, когда вы начинаете использовать async/wait.

Это проблема, поскольку вы обычно вызываете Resolve<T> один раз в начале запроса. Это загрузит полный графический объект, включая ваши сервисы, зарегистрированные в стиле жизни в потоке. Когда ASP.NET завершает запрос в другом потоке, это означает, что графа разрешенных объектов перемещается в этот новый поток, включая все зарегистрированные экземпляры в потоке.

Поскольку эти экземпляры зарегистрированы как Per Thread, они, вероятно, не подходят для использования в другом потоке. Они почти наверняка не являются потокобезопасными (иначе они будут зарегистрированы как Singleton). Поскольку первый поток, который изначально начал запрос, уже свободен для сбора новых запросов, мы можем столкнуться с ситуацией, когда два потока обращаются к этим экземплярам Per Thread одновременно. Это приведет к условиям гонки и ошибкам, которые трудно диагностировать и найти.

Таким образом, использование Per Thread - плохая идея. Вместо этого используйте стиль жизни, который имеет ясную область (неявное или явно определенное начало и конец). Образ жизни в Интернете, который реализуется большинством инфраструктур DI, часто неявно охвачен (вы не должны сами его заканчивать).

Специфично для вашего вопроса

Чтобы все ухудшилось, сообщение в блоге, на которое вы ссылаетесь, содержит ошибку конфигурации. ICatalogService определяется стилем жизни в потоке. Однако эта услуга зависит от службы IDALContext, которая определяется как Transient. Поскольку ссылка на экземпляр IDALContext хранится как частное поле внутри CatalogService, это означает, что DALContext живет, пока выполняется ICatalogService. Это проблема, потому что IDALContext определяется как Transient и, вероятно, не является потокобезопасным.

Общее правило образа жизни

Общее правило заключается в том, чтобы компоненты зависели только от служб с равным или более продолжительным временем жизни. Таким образом, переходный процесс может зависеть от Singleton, но не наоборот.

Поскольку компонент, зависящий от Перья, обычно живет очень долго, он может, как правило, безопасно зависеть только от других экземпляров Per Thread или Singleton. И поскольку ASP.NET может разделить один запрос на несколько потоков, небезопасно использовать Per Thread в контексте приложения ASP.NET(как MVC, Web Forms, так и особенно Web API).