Страница: 1 |
|
Вопрос: Ногами не бить - я новенький
|
Добавлено: 25.03.11 16:23
|
|
Автор вопроса: час1
|
написал я функцию:
Function FUN_CREATE_FILE(ByVal NAME_FILE As String) As Boolean
' Создаем новый текстовой файл с именем NAME_FILE
Try
File.Create(NAME_FILE)
Return True
Catch ex As Exception
Return False
Finally
End Try
End Function
работает она нормально, но при анализе кода - мне сообщают, что:
Предупреждение 31 CA2000 : Microsoft.Reliability : В методе 'FILE_MOD.FUN_CREATE_FILE(String)' вызовите System.IDisposable.Dispose для объекта 'File.Create(NAME_FILE)' перед тем, как все ссылки на него будут вне области видимости. C:\1_Текущее\1_2010\MODULS\MODULS\FILE_MOD.vb 75 MODULS
потыкался - посмотрел что написано об этом в msdn? поискал ответы в инете.
ответы есть - примеры то же - ничё не понимаю.
Как в моём случае высвободить уже неиспользуемые ресурсы?
Ответить
|
Номер ответа: 3 Автор ответа: СанСаныч
Вопросов: 3 Ответов: 118
|
Профиль | | #3
|
Добавлено: 25.03.11 20:24
|
потыкался - посмотрел что написано об этом в msdn? поискал ответы в инете.
ответы есть - примеры то же - ничё не понимаю.
Может, есть смысл забросить программирование? Или в универ на нужную специальность поступить...
Ответить
|
Номер ответа: 5 Автор ответа: Artyom
Разработчик
Вопросов: 130 Ответов: 6602
|
Профиль | | #5
|
Добавлено: 25.03.11 21:58
|
Лёха пишет:
Ты используешь управляемый код,все не нужные ресурсы освободит GC.
неправда.
Хоть код и управляемый, но GC может освободить только управляемые ресурсы. О не управляемых ресурсах он ничего не знает.
По поводу предупреждения в первом сообщении.
Метод File.Create создает файл и возвращает тебе экземпляр FileStream, через который можно выполнять запись/чтение данных.
--------------
Посмотирм что происхоидт на более нижнем уровне.
Можно предположить, что для создания вызывается функция Win32API CreateFile. Она возвращает указать (handle) на объект файла (file), который в данном случае уже является неуправляемым объектом. Этот handle записывается в какое-то внутреннее поле экземпляра класса FileStream. Кстати его можно узнать, обратившись к свойству FileStream.SafeFileHandle
В документации на CreateFile мы видим что:
When an application is finished using the object handle returned by CreateFile, use the CloseHandle function to close the handle. This not only frees up system resources, but can have wider influence on things like sharing the file or device and committing data to disk. Specifics are noted within this topic as appropriate.
То есть после того как работа с файлом завершена, необходимо вызвать метод CloseHandle, указав handle объекта, который мы хотим закрыть. Это не только предотвратит утечку памяти, но также освободит файл от блокировки, дав возможность другим приложениям работать с ним (если общий доступ был запрещен при создании FileStream), то есть, закрывать файл желательно как можно раньше, в идеале - как только работа с ним закончилась.
--------------
Разумеется, дотнет это не VB6, в дотнете нет необходимости вручную вызывать метод CloseHandle. Каждый класс, который создает неуправляемые ресурсы, должен знать как неуправляемые ресурсы удалять. И предоставлять возможность это сделать.
По общепринятой рекомендации класс, с которым связаны неуправляемые ресурсы, или которому просто по какой-то причине нужно выполнять детерменированное удаление управляемых или неуправляемых ресурсов, должен реализовывать интерфейс IDisposable. В этом интерфейсе только один метод - Dispose, при вызове которого и должно происходить удаление ресурсов и другие операции. Например, в случае FileStream перед закрытием файла в него предварительно будет сброшено содержимое буфера.
То есть, когда ты завершил работу с объектом, который реализует IDisposable, нужно вызвать у него метод Dispose.
- Dim Stream As FileStream = File.Create("c:\1.txt")
-
- Stream.Dispose()
Нужно учитывать, что если во время работы с потоком произойдет какое-то исключение, то метод Dispose вызван не будет. Поэтому, для того чтоб гарантировать вызов этого метода, нужно модифицировать код, выполняя вызов Dispose в блоке Finally:
- Dim Stream As FileStream
- Try
- Stream = File.Create("c:\1.txt")
-
- Finally
- If Stream IsNot Nothing Then
- Stream.Dispose()
- End If
- End Try
Ввиду излишней сложности данной конструкции, в язык была введена более простая конструкция (кстати в C# она была еще с первой версии)
- Using Stream = File.Create("c:\1.txt")
-
- End Using
Ты можешь использовать последний приведенный вариант кода. Просто в твоем случае никакого кода работы с потоком не будет.
----------------------
В .NET есть предохранитель на тот случай если программист забудет вызвать метод Dispose у объекта и он пропадет из области видимости. В этом случае до него доберется сборщик мусора, увидит что на него нет ссылок. А также увидит что у объекта есть финализатор, и поставит его в очередь на финализацию. После этого у объекта будет вызван финализатор. В финализеторе есть проверка того, был ли вызван Dispose, и если не был, то он будет вызван принудительно. Таким образом, неуправляемый ресурс все равно будет удален, только позже.
Но здесь есть 2 проблемы.
1. Время запуска сборщика мусора и финализаторов недетерменировано. То есть, может пройти определенное время между тем моментом когда работа с файлом завершена, и моментом запуска сборщика мусора. Все это время неуправляемые ресурсы будут висеть (а это могут быть и довольно дорогие ресурсы). Кроме того, если работа с файлом была длительное время, то объект мог уйти во 2-е поколение, и тогда есть большая вероятность, что при запуске сборщика мусора он не доберется до этого объекта и он будет продолжать висеть. И будет удален только тогда когда кончится свободная память и сборщик мусора не возьмется за 1 и 2 поколение объектов. Также между сборкой мусора и запуском финализаторов может пройти неопределенное время.
2. CLR не гарантирует что финализаторы будут запущены, даже если объект удален при сборке мусора. Хотя обычно финализаторы запускаются, но на 100% нельзя на это полагаться.
Вызов Dispose при финализации не всегда выполняется автоматически, это не фича CLR. Вызов Dispose будет только в том случае, если в классе есть финализатор, и если программист, делавший этот класс, сделал в финализаторе вызов Dispose. Поэтому не нужн думать, что это актуально для каждого объекта.
Ответить
|
Страница: 1 |
Поиск по форуму