Dispose () не предотвращает исключение нехватки памяти - PullRequest
1 голос
/ 31 марта 2012

У меня огромный лог-файл, в котором около 15 миллионов строк. Я должен перенести все эти строки в базу данных Oracle. Вот что я делаю для этого:

  1. Я читаю строки в DataTable (строки разделяются запятыми так, чтобы они образуют столбцы). Я прочитал строки StreamReader и поместил его в используя его, чтобы избавиться от него, когда закончит читать.
  2. Я поставил счетчик, который увеличивается на 1 в каждой строке, считываемой в таблицу данных.
  3. Когда этот счетчик достигает 40.000, я импортирую все строки в базу данных с помощью OracleBulkCopy.
  4. Когда импорт завершен, я говорю:

    bulkCopier.Dispose();<br> dataTable.Dispose();

Однако это никак не помогает. В диспетчере задач я вижу, как увеличивается использование памяти до тех пор, пока она не будет исчерпана. Теперь мой вопрос: Dispose() метод не освобождает память немедленно? Если это так, то почему использование памяти накапливается, как будто все объекты DataTable и OracleBulkCopy продолжают сохранять память.

Ответы [ 3 ]

5 голосов
/ 31 марта 2012

Утилизация не освобождает управляемую память немедленно.Dispose освобождает любые блокировки для неуправляемых ресурсов (например, памяти) при вызове dispose и не имеет ничего общего с управляемой памятью.

Весь объект Datatable заполнен управляемыми объектами в управляемой памяти.Звонить. Распоряжаться на нем ничего не будет делать.Вам необходимо очистить все данные из DataTable (для этого есть удобный метод Clear), который позволит сборщику мусора освободить память в какой-то момент времени в будущем, когда возникнет необходимость очистки.

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

3 голосов
/ 31 марта 2012

Нет, распоряжайтесь сигналами внутренних ручек, которые должны быть сняты. Объект с Dispose фактически получает GC-d позже.

Если это IDisposable, вы должны попробовать использовать их в блоке using (), в соответствии с документацией, которая высвобождается автоматически после использования.

Вы можете форсировать сбор GC с помощью GC.Collect, но я не думаю, что эти объекты являются несвободным мусором, .NET лучше, чем этот.

Разве вы не можете создать мини-дамп и проверить, что застревает и почему?

2 голосов
/ 31 марта 2012

Теперь мой вопрос заключается в том, не метод Dispose () освободить память немедленно

Не обязательно. Единственная память, которую это освободит, является той суммой, выделенной неуправляемыми ресурсами. Это не повлияет на управляемую кучу.

Что вам нужно сделать, это убедиться, что нет никаких ссылок на эти висящие DataTable экземпляры. Возможно, вам придется удалить их из коллекции или null вывести ссылки на переменные по мере необходимости.

...