SemaphoreSlim часто кидают в код как самое простое решение и успокаиваются. В проде этого мало, ведь малейшая ошибка с Release, областью блокировки или per-key словарем легко превращается в дедлок, гонку или утечку памяти.
Самый частый фейл — банальное «забыли Release». Исключение между
WaitAsync и finally и семафор навсегда занят поэтому все будущие вызовы повисают. Помогает только жесткое правило всегда оборачивать WaitAsync в try finally и не вставлять лишний код между ними особенно никакой логики которая может бросить исключение.Вторая классика — блокировки внутри async кода. Варианты вроде
_lock.Wait() или .Result внутри секции под SemaphoreSlim открывают прямую дорогу к дедлокам, потому что блокирующий вызов держит поток, а продолжение ждет этот же поток. Общий принцип не блокировать внутри асинхронной критической секции если нужно синхронное API выносить его в
Task.Run до входа в lock.Поэтому в проде почти всегда лучше прятать SemaphoreSlim за абстракцией AsyncLock. Обертка с
LockAsync() возвращающей IDisposable снимает часть рисков.📍 Навигация: Вакансии • Задачи • Собесы
🐸Библиотека шарписта
#il_люминатор
