Нужно ли мне утилизировать Семафор?

Согласно документации:

"a SemaphoreSlim не использует семафор ядра Windows".

Существуют ли какие-либо специальные ресурсы, используемые SemaphoreSlim, которые делают важным вызов Dispose, когда SemaphoreSlim больше не будет использоваться?

Ответ 1

Да.

Он может использовать ManualResetEvent, который использует SafeWaitHandle, который является SafeHandle, и имеет неуправляемый дескриптор.

Вы можете увидеть его здесь в ссылке здесь.

SafeHandle является окончательным, поэтому, если вы не распоряжаетесь им (путем утилизации SemaphoreSlim), он перейдет к финализатору, который должен будет сделать это за вас. Поскольку финализатор представляет собой один поток, он может перегружаться в определенных ситуациях, поэтому всегда рекомендуется располагать объекты, подлежащие окончательной обработке.

Ответ 2

Если вы используете свойство AvailableWaitHandle, , затем Да, вы должны вызвать Dispose() для очистки неуправляемых ресурсов.

Если вы не получили доступ к доступнойWaitHandle, , то No, вызов Dispose() не будет делать ничего важного.

SemaphoreSlim будет создавать ManualResetEvent по требованию, если вы получите доступ к доступномуWaitHandle. Это может быть полезно, например, если вам нужно ждать нескольких дескрипторов. Если вы выполняете доступ к свойству AvailableWaitHandle, а затем не можете вызвать Dispose(), у вас будет утечка ManualResetEvent, который предположительно переносит дескриптор на неуправляемый ресурс CreateEvent, для которого требуется соответствующий вызов CloseHandle для очистки.

Как отмечали другие плакаты, вы должны вызывать Dispose(), когда закончите с любым объектом, который реализует IDisposable. В этом случае существует несколько рисков для игнорирования этой практики, хотя это может быть технически безопасно:

  • Мои операторы основаны на исходном исходном коде для .NET 4.6.1. Всегда существует тонкая (каламбурная) возможность, что какая-то будущая версия фреймворка изменит СемафорСлим на место, где требуется Dispose().
  • Если ваш SemaphoreSlim открыт вне вашего класса, вызывающий код может ссылаться на свойство AvailableWaitHandle, не понимая, что ваш класс не использует SemaphoreSlim и не создает неуправляемую утечку ресурсов.

Ответ 3

Вы всегда должны вызывать Dispose() для любого класса, реализующего IDisposable (или помещать его в оператор using), а не основывать свое решение на его внутренней реализации. Автор класса уже принял это решение для вас, реализовав интерфейс IDisposable.

Ответ 4

Для многих других классов я бы согласился с i3arnon, но для SemaphoreSlim я поеду с комментарием Тима. Если вы используете SemaphoreSlim в классе низкого уровня и должны его утилизировать, то практически все в вашей программе станет IDisposable, если на самом деле это не обязательно. Это тем более верно, что AvailableWaitHandle довольно специализирован и обычно не используется.

Для защиты от других кодеров, обращающихся к доступномуWaitHandle, вы можете просто обернуть его в класс, который нельзя использовать. Вы видите это, например, в обертках Клири и Гензельма, оба основаны на записи Стивена Тууба (который, кстати, не Dispose).

P.S. Что касается договора IDisposable, его следует указывать только в документации, которую Dispose требуется только в том случае, если доступ к ДоступнойWaitHandle.