Ответ 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).