Он запускается успешно в первый раз,
но если я буду запускать его снова, я продолжаю получать
System.OutOfMemoryException. Какие
Есть несколько причин, по которым это может быть
происходит?
Независимо от того, что сказали другие, ошибка не имеет ничего общего с забыванием утилизировать DBCommand или DBConnection, и вы не исправите ошибку, выбрав одну из них.
Ошибка связана с вашим набором данных, который содержит почти 600 000 строк данных. Очевидно, ваш набор данных потребляет более 50% доступной памяти на вашем компьютере. Очевидно, вам не хватит памяти, когда вы вернете другой набор данных того же размера до того, как первый будет собран сборщиком мусора. Все просто.
Вы можете решить эту проблему несколькими способами:
Подумайте о возврате меньшего количества записей. Лично я не могу себе представить время, когда возвращение 600K записей было когда-либо полезным для пользователя. Чтобы свести к минимуму возвращаемые записи, попробуйте:
Ограничение вашего запроса первыми 1000 записями. Если по запросу возвращено более 1000 результатов, сообщите пользователю о необходимости сузить результаты поиска.
Если ваши пользователи действительно настаивают на том, чтобы видеть столько данных одновременно, попробуйте разбить их на страницы. Помните: Google никогда не показывает вам все 22 баджиллионных результата поиска одновременно, он показывает вам около 20 записей одновременно. Google, вероятно, не хранит в памяти все 22 баджиллионных результата одновременно, возможно, он считает, что его память более эффективна для запроса базы данных для создания новой страницы.
Если вам просто нужно перебрать данные и вам не нужен произвольный доступ, попробуйте вместо этого вернуть устройство чтения данных. Считыватель данных одновременно загружает в память только одну запись.
Если ни один из них не является опцией, вам нужно заставить .NET освободить память, используемую набором данных, перед вызовом вашего метода одним из следующих методов:
Удалите все ссылки на ваш старый набор данных. Все, что удерживает референс вашего набора данных, не позволит ему восстановить память.
Если вы не можете обнулить все ссылки на ваш набор данных, удалите все строки из набора данных и любые объекты, связанные с этими строками. Это удаляет ссылки на датаров и позволяет их использовать сборщику мусора.
Я не думаю, что вам нужно будет позвонить GC.Collect()
, чтобы запустить цикл генов. Мало того, что обычно вызывать GC.Collect()
- плохая идея, поскольку достаточное давление памяти приведет к тому, что .NET сам вызовет сборщик мусора.
Примечание: вызов Dispose для вашего набора данных не освобождает память, не вызывает сборщик мусора и не удаляет ссылку на ваш набор данных. Dispose используется для очистки неуправляемых ресурсов, но DataSet не имеет никаких неуправляемых ресурсов. Он реализует только IDispoable, потому что он унаследован от MarshalByValueComponent, поэтому метод Dispose для набора данных практически бесполезен.