Использование 'using' с утилитами потоков в C # - когда вызывается Dispose? - PullRequest
3 голосов
/ 09 июня 2011

Я разрабатываю некоторые утилиты для управления потоками для игрового сервера и экспериментирую с использованием IDisposable "токена", чтобы я мог использовать такой код:

using(SyncToken playerListLock = Area.ReadPlayerList())
{
    //some stuff with the player list here
}

Идея заключается в том, что яполучить блокировку чтения в списке игроков в области, и он автоматически разблокируется, когда он выходит из области действия с помощью блока using.Пока что все это реализовано и работает, но меня беспокоит время вызова Dispose().

. Переменная SyncLock просто помечается для удаления, когда программа покидает блок using, а затембыть очищенным сборщиком мусора в какой-то момент позже, или текущий поток выполняет метод Dispose() как часть выхода из блока using?

Этот шаблон в основном RAII, где блокировкавыделяемый ресурс.Пример этого паттерна (т. Е. Использование IDisposable "токена") также использовался Джоном Скитом в его MiscUtils здесь

Ответы [ 8 ]

11 голосов
/ 09 июня 2011

Он очищается сразу после выхода из области действия using.

По сути, этот

using(SyncToken playerListLock = Area.ReadPlayerList())
{
    //some stuff with the player list here
}

является синтаксическим сахаром для

IDisposable playerListLock;
try {
    playerListLock = Area.ReadPlayerList();
}
finally {
    if (playerListLock != null) playerListLock.Dispose();
}

Сама цельиз using - включить RAII-подобную функциональность в C #, которая не имеет детерминированного уничтожения.

3 голосов
/ 09 июня 2011

Dispose вызывается при выходе из области действия using. Синтаксический сахар для:

MyObj instance = null;
try
{
  instance = new MyObj();
}
finally
{
  instance.Dispose();
}
2 голосов
/ 09 июня 2011

Dispose() вызывается немедленно при выходе из блока using.
using является более или менее эквивалентом C # идиомы RAII в C ++.

1 голос
/ 09 июня 2011

using блоки - это просто синтаксический сахар блока try-finally:

using (var myObject = new MyObject())
{
    ...
}

эквивалентно:

MyObject myObject = null;

try
{
    myObject = new MyObject();
    ...
}
finally
{
    if (myObject != null)
    {
         myObject.Dispose();
    }
}

Таким образом, у вас есть уверенность, что Dipose () будет вызван сразу после выхода из блока using.

Совершенно другое дело, когда GC собирает объект. Нет гарантии того, когда это произойдет.

1 голос
/ 09 июня 2011

Когда вы покидаете область использования блока, вызывается функция Dispose (), освобождающая выделенный ресурс, однако SyncToken собирается GC при каждом запуске.

1 голос
/ 09 июня 2011

Dispose вызывается в конце блока using, вам следует реализовать Dispose для SyncToken, чтобы SyncLock мог быть детерминированно освобожден, и в этом весь смысл шаблона Dispose.

1 голос
/ 09 июня 2011

Документы using утверждают, что:

Оператор using гарантирует, что Dispose вызывается, даже если при вызове методов объекта вызывается исключительная ситуация.Вы можете достичь того же результата, поместив объект в блок try, а затем вызвав Dispose в блоке finally;на самом деле, именно так оператор using транслируется компилятором.

Так что да, он вызывается, как только вы выходите из блока.

0 голосов
/ 09 июня 2011

Метод Dispose вызывается, как только ваша переменная выходит из области видимости, сборщик мусора запускается в какой-то неопределенной точке позже и не влияет на это.

Кроме того, посмотрите на это для простого сравнения того, что происходит под: с использованием и IDisposable

...