Есть ли Время, в которое можно проигнорировать IDisposable. Расположить?

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

Но что относительно "прошлого момента" перед завершением процесса? Если Ваши IDisposables не были явно расположены тем моментом времени, не это верный, что это больше не имеет значения? Я спрашиваю, потому что неуправляемые ресурсы, под CLR, представлены объектами ядра - и завершение процесса win32 освободит все неуправляемые ресурсы / объекты ядра так или иначе. Сказанный по-другому, никакие ресурсы не останутся "пропущенными" после того, как процесс завершится (независимо, если Располагают (), был обращен задержание IDisposables).

Кто-либо может думать о случае, где завершение процесса все еще оставило бы пропущенный ресурс, просто потому что Располагают (), не был явно обращен один или несколько IDisposables?

Не неправильно понимайте этот вопрос: Я не пытаюсь выровнять по ширине игнорирование IDisposables. Вопрос является просто техническо-теоретическим.

Править: И что относительно моно работы Linux? Завершение процесса там так же "надежно" при чистке неуправляемых "утечек?"

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ: Хотя "другое использование" может существовать для IDisposables, мой фокус находится строго на утечках ресурсов. Я услышал два ответа: (1) если Ваш процесс откажется завершаться, то у Вас будет утечка и (2) да, ресурсы могут протечь, даже если процесс завершается. Я, конечно, соглашаюсь с объектом (1), хотя это недалеко от объема того, что я после. Иначе объект (2) точно, что я ищу, но я не могу встряхнуть чувство, что это - просто предположение. Jeffrey Richter ("Windows через C/C++") объясняет, что (корректно) завершенный процесс Win32 не уедет, протек или осиротевшие ресурсы. Почему был бы процесс, содержащий изменение CLR это? Где документация, определенный пример, или теоретический сценарий, который дает веру в идею, что возможность очистки процесса Win32 поставлена под угрозу при использовании CLR?

6
задан Brent Arias 1 February 2011 в 17:12
поделиться

5 ответов

С технической точки зрения, все зависит от того, что делает IDisposable. Он использовался для многих вещей, а не только для неуправляемых ресурсов.

Например, работая над приложением Outlook, я построил небольшую симпатичную абстракцию Outlook API. Вложения особенно раздражали при работе с потоками, потому что вам нужно было сохранить их во временном файле, поработать с ними, а затем очистить.

Итак, моя абстракция выглядела примерно так:

OutlookMailItem mailItem = blah;
using (Stream attachmentStream = mailItem.OpenAttachment("something.txt")) {
   // work with stream
}

Когда Dispose был вызван для AttachmentStream, временный файл, на котором он был основан, был удален. В этом случае, если Dispose не был вызван, временный файл никогда не будет очищен. При запуске у меня был процесс поиска этих потерянных файлов, но я решил представить это в качестве примера.

На самом деле, почти все реализации IDisposable, которые заключают в оболочку какой-либо сокет, дескриптор или транзакцию, будут просто очищены операционной системой после завершения процесса. Но очевидно, что это похоже на благополучие. Избегайте этого, если можете.

2
ответ дан 17 December 2019 в 04:44
поделиться

Вы пишете собственный код для освобождения объектов в одноразовом классе. Вам нужно писать код для бесплатного неуправляемого и управляемого кода.

Вот почему нам нужна функция Dispose . Освобождение памяти не происходит автоматически, как вы сказали в случае с неуправляемым кодом.

Если вы думаете, что неуправляемый код автоматически освобождается ОС, это неправда. Существует множество дескрипторов и блокировок, которые могут оставаться активными, если они не удаляются должным образом вашим приложением.

0
ответ дан 17 December 2019 в 04:44
поделиться

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

И да, моя программа раньше оказывалась в состоянии зомби, а затем клиент жалуется, что программа больше не работает, потому что программа не может подключиться к последовательному порту при перезапуске. В результате пользователь либо убивает процесс в диспетчере задач, либо перезагружается, что не является особенно удобной задачей.

1
ответ дан 17 December 2019 в 04:44
поделиться

Во время совместного завершения работы домен приложения выгружается, что вызывает выполнение всех финализаторов:

Из документации Object.Finalize :

Во время завершения работы домена приложения Finalize автоматически вызывается для объектов, которые не освобождены от завершения, даже тех, которые все еще доступны.

Таким образом, вы в безопасности при завершении работы, пока выполняются два критерия:

  • Каждый IDisposable объект, который все еще жив, имеет правильно реализованный финализатор (верно для классов Framework, может не соответствовать менее надежные библиотеки); и

  • На самом деле это совместное завершение работы, а не аварийное завершение, такое как жесткое завершение процесса, Ctrl-C в консольном приложении или Environment.FailFast .

Если любой из этих двух критериев не выполняется, возможно, ваше приложение удерживает глобальные неуправляемые ресурсы (например, мьютекс), которые на самом деле будут давать утечку. Поэтому всегда лучше вызывать Dispose заранее, если есть возможность. В большинстве случаев вы можете положиться на CLR и финализаторы объектов, которые сделают эту работу за вас, но лучше перестраховаться.

2
ответ дан 17 December 2019 в 04:44
поделиться

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

Небольшой пример, чтобы дать вам представление:

    sealed class Logger : IDisposable
    {
        private bool _disposed = false;

        public Logger()
        {
            System.IO.File.AppendAllText( @"C:\mylog.txt", "LOG STARTED" );
        }

        ~Logger()
        {
            Dispose();
        }

        public void Dispose()
        {
            if ( !_disposed )
            {
                System.IO.File.AppendAllText( @"C:\mylog.txt", "LOG STOPPED" );
                _disposed = true;
            }
        }

        public void WriteMessage( string msg )
        {
            System.IO.File.AppendAllText( @"C:\mylog.txt", "MESSAGE: " + msg );
        }
    }

Обратите внимание, что этот класс Logger не «удерживает» какие-либо ресурсы в стиле объекта ядра. Он открывает файл и сразу закрывает его. Однако есть такая логика, что он должен писать «LOG STOPPED», когда объект уничтожается.Эта логика - то, что GC не может понять - и здесь можно использовать IDisposable .

Следовательно, вы не можете рассчитывать на то, что Windows очистит объекты ядра после вас. Может быть, есть что-то, чего не знает даже Windows.

При этом, однако, при условии, что ваши одноразовые объекты правильно написаны (т.е. вызывают Dispose в финализаторе), они все равно будут удалены CLR после выхода из процесса.

Итак, ответ: да, нет необходимости вызывать Dispose непосредственно перед выходом из проекта. Но НЕ потому, что одноразовые ресурсы являются объектами ядра (потому что они не обязательно таковыми).


Править

Как правильно заметил Джош Эйнштейн, на самом деле не гарантируется запуск финализаторов при выходе из процесса. Итак, ответ будет следующим: всегда вызывайте Dispose, просто для того, чтобы засудить

0
ответ дан 17 December 2019 в 04:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: