Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Утечка дескрипторов 
:(
    Опции темы
N1ko
Дата 25.5.2010, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



Здравствуйте. Есть программа, которая сканируют 7 Гб dbf файлов и вставляет инфу из них в другую СУБД. Сканирует их до тех пор, пока не вылетает исключение "Недостаточно системных ресурсов". Запустив програму заново и при этом запустив диспетчер задач,увидел что количество дескрипторов непрерывно растёт. Когда доходит почти до 30000 собственно и вылетает исключение. Нашёл в интренете инфу, что такая проблема возникает в связи с использованием многопоточности.(Реализую её через стандартную компоненту BackGrounWorker) А вот как её решить не совсем понятно. Помогите плз кто чем может. 

PM MAIL ICQ   Вверх
jonie
Дата 25.5.2010, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Вам нужно пройтись по всему коду в поисках объектов, которые вы создаете, классы которых наследуются от IDisposable [http://msdn.microsoft.com/en-us/library/system.idisposable.aspx]. Далее очень внимательно погуглить по этому интерфейсу и почитать MSDN. Думаю ресурсы как раз и текут и вас в силу недетерменированной природы деструкторов (финализаторов) в .NET - среда просто не успевает разрушать объекты, содержащие ссылки на неуправляемые ресурсы (дескрипторы), и винда глушит ваше приложение.... возможно также, что ошибка в библиотеках которые вы используете подобная имеется.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
N1ko
Дата 25.5.2010, 23:02 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



То есть если я правильно понял нужно реализовать IDisposable у всех самодельных классов? 
PM MAIL ICQ   Вверх
jonie
Дата 25.5.2010, 23:07 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



N1ko, нет неправильно. IDisposable нужен если вам нужно относительно детерменированное (читай "по запросу вами") очистка ресурсов например.
Вам надо пройтись по коду и найти места где вы используете классы, наследуемые от IDisposable ... например OleDBConnection наследуется...а дальше using-и использовать или try..finally 
В общем тут почитайте http://www.rsdn.ru/article/dotnet/GCnet.xml 


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
N1ko
Дата 26.5.2010, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



Пробовал как вы сказали. Прочитал кучу статей. Уже по 5 раз прошёлся по всему коду. Сделал Dispose у всего что только можно. Ничего не получается ((
Вот выложил код, котрый непосредственно отвечает за считывание данных из одного DBF файла и вставляет их в SQLite. Програма в  принципе работает без утечки в случае если я не закрываю OleDbReader а в final прописываю 
 GC.Collect();
 GC.WaitForPendingFinalizers();
Но где то на 600-700 мб просканеных дбф файлов програма начинает работать очень медленно. Судя по всему из-за сборщика мусора. Возможно глядя на код Вы найдёте ошибку. Буду очень благодарен за Вашу помощ.
Код

 public bool InsertDBFData(DBFile DbfFile, DbConnection conSQLiteCon)
        {
            bool _isPerformed;
            try
            {
                OleDbDataReader _oleDBReader = DbfFile.ReadData().ExecuteReader();
                SetValues(0, DbfFile.Path);
                DataTable _dbfSchemaTable = _oleDBReader.GetSchemaTable();
                while (_oleDBReader.Read())
                {
                    for (int i = 0; i < _dbfSchemaTable.Rows.Count; ++i)
                    {
                        int _fieldindex = table.FindFieldIndex(_dbfSchemaTable.Rows[i][0].ToString());
                        if (_fieldindex != -1)
                        {
                            SetValues(_fieldindex, _oleDBReader[i].ToString());
                        }
                    }
                    cmdInsertString.Connection = (SQLiteConnection)conSQLiteCon;
                    try
                    {
                        cmdInsertString.ExecuteNonQuery();
                    }
                    catch
                    {
                         MessageBox("Строка не прочитана");
                    }
                }
                _oleDBReader.Close(); - если убираю закрытие и Dispose у OleDBDataReader, тогда работает нормально
               _oleDBReader.Dispose();
                _isPerformed = true;
            }
            catch (OleDbException Ex)
            {
                Ex.ToString();
                sWarning = " Невозможно считать файл.";
                _isPerformed = false;
            }
            finally
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            return _isPerformed;
        }


Это сообщение отредактировал(а) N1ko - 26.5.2010, 12:29
PM MAIL ICQ   Вверх
NightmareZ
Дата 26.5.2010, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


[хакер]
**


Профиль
Группа: Участник
Сообщений: 699
Регистрация: 10.8.2006

Репутация: 1
Всего: 13



Цитата(N1ko @  26.5.2010,  12:27 Найти цитируемый пост)

GC.Collect();
GC.WaitForPendingFinalizers();


Я считаю, что этого делать не нужно. Нужно лишь вызывать Dispose.

Цитата(N1ko @  26.5.2010,  12:27 Найти цитируемый пост)
Возможно глядя на код Вы найдёте ошибку.


Ты уверен, что ошибка тут? Не пробывал отслеживать, где дескрипторы создаются и где уничтожаются?


--------------------
NightmareZ.net - мой блог и сайт, мои проекты и прочий трэш
Ely-Art.ru - наша маленькая домашняя арт-студия
mugcraft.ru - кружки на любой вкус
PM WWW ICQ Skype GTalk AOL YIM   Вверх
N1ko
Дата 27.5.2010, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



А может ли быть утечка дескрипторов из-за того что я сначала создаю SQLiteCommand, создаю в нём параметры. Но не устанавливаю в них Value. А уже только потом меняю эти значения в цикле много раз. Для этого SQLiteCommand не делаю Dispose()

И ещё мне вообще не понятно почему когда я убираю
_oleDBReader.Close(); 
_oleDBReader.Dispose();
но оставляю GarbageCollector всё работает нормально без утечек. 

Это сообщение отредактировал(а) N1ko - 27.5.2010, 11:03
PM MAIL ICQ   Вверх
mrbrooks
Дата 27.5.2010, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 17
Всего: 306



Цитата(N1ko @  25.5.2010,  19:32 Найти цитируемый пост)
Есть программа, которая сканируют 7 Гб dbf файлов и вставляет инфу из них в другую СУБД. Сканирует их до тех пор, пока не вылетает исключение "Недостаточно системных ресурсов".

а каков механизм сканирования?
основан на DataReader, и если да, какой запрос его формирования?

Добавлено через 4 минуты и 49 секунд
Цитата(N1ko @  26.5.2010,  13:27 Найти цитируемый пост)
               
                GC.Collect();
                GC.WaitForPendingFinalizers();

этот код в блоке finally не нужен. Там достаточно _oleDBReader.Close(). И, следовательно, последний можно удалить из try catch вместе с 
_oleDBReader.Dispose()
PM MAIL   Вверх
N1ko
Дата 27.5.2010, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



Для сканирования действительно использую DataReader. Но к сожалению не совсем понял, что Вы имели ввиду под запросом формирования.

Цитата(mrbrooks @ 27.5.2010,  11:08)
этот код в блоке finally не нужен. Там достаточно _oleDBReader.Close(). И, следовательно, последний можно удалить из try catch вместе с 
_oleDBReader.Dispose()


А как же я в блок finally вставлю _oleDBReader.Close(), если у него область видимости очень маленькая. Ведь Oledbreader я создаю в блоке try.  

Это сообщение отредактировал(а) N1ko - 27.5.2010, 11:21
PM MAIL ICQ   Вверх
mrbrooks
Дата 27.5.2010, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 17
Всего: 306



Цитата(N1ko @  27.5.2010,  12:19 Найти цитируемый пост)
Но к сожалению не совсем понял, что Вы имели ввиду под запросом формирования. 

Имел ввиду, как заполняете исходный  DataReader, который обращается *.dbf.
если я правильно понимаю, то так:

Код

       OleDbDataReader _oleDBReader = DbfFile.ReadData().ExecuteReader();

PM MAIL   Вверх
N1ko
Дата 27.5.2010, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



Да. DbfFile - экземпляр класа, который хранит информацию о местонахождении DFB файла, его размере и тп. Метод ReadData() вытаскивает из него всю инфу. 

В finally вряд ли получится закрывать Reader, потому что область видимости не позволяет.(Если оюъявить oledbreader перед блоком try) тогда в finally пишет ошибку "unassigned local variable"

Это сообщение отредактировал(а) N1ko - 27.5.2010, 11:44
PM MAIL ICQ   Вверх
mrbrooks
Дата 27.5.2010, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 17
Всего: 306



Цитата(N1ko @  27.5.2010,  12:38 Найти цитируемый пост)
В finally вряд ли получится закрывать Reader, потому что во ппервых область видимости не позволяет.(Если оюъявить oledbreader перед блоком try) тогда в finally пишет ошибку "unassigned local variable" 

ну это не проблема - можно и так:

Код

try
{
   using (OleDbDataReader _oleDBReader = DbfFile.ReadData().ExecuteReader())
  {
         //арбайтен
  }
}
catch
{
//...
}


не нужен ни Close() ни finnaly


Цитата(N1ko @  27.5.2010,  12:38 Найти цитируемый пост)
Метод ReadData() вытаскивает из него всю инфу. 

вот это и интересно. думаю не 7Gb?  smile 
PM MAIL   Вверх
N1ko
Дата 27.5.2010, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



Нет файлов очень много, каждый из которых от 20 до 400 кб.

В общем суть програмы следующая . Пользователь указывают папку, которую нужно просканировать на наличие DBF файлов, вытащить из них инфу и вставить в СУБД. Делаю я это посредством рекурсии.  Соответственно DbfFile.ReadData() работает не с 7 Гб одновременно а работает с маленькими объёмами  smile 

А можно ли как то очистить ресурсы выделенные под String после их затирания? Как я уже писал всё время использую один и то же SQLiteCommand, затирая Value для всех параметров и ставя на их место новые.

Это сообщение отредактировал(а) N1ko - 27.5.2010, 12:10
PM MAIL ICQ   Вверх
mrbrooks
Дата 27.5.2010, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 17
Всего: 306



Цитата(N1ko @  27.5.2010,  13:04 Найти цитируемый пост)
А можно ли как то очистить ресурсы выделенные под String после их затирания?

string.Empty?


Цитата(N1ko @  27.5.2010,  13:04 Найти цитируемый пост)
В общем суть програмы следующая . Пользователь указывают папку, которую нужно просканировать на наличие DBF файлов, вытащить из них инфу и вставить в СУБД. Делаю я это посредством рекурсии.  Соответственно DbfFile.ReadData() работает не с 7 Гб одновременно а работает с маленькими объёмами

В целом ясно. Идея в принципе работоспособная (настораживает только рекурсия - net обладает отличной библиотекой по работе с каталогами).
Имхо проблема, скорее всего просто в проектировании.  По данному примеру тяжело судить о том что творится в целом. 
Подозреваю, что работа с базами у вас свалена вся в один класс, a стоило бы разделить работу с сущностями по отдельным, etc
PM MAIL   Вверх
N1ko
Дата 27.5.2010, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

Репутация: нет
Всего: нет



Нет Я уже на этом прокололся недавно. И всё разграничил по сущностям. Для базы создал классы реализующие обёртку для самой БД, таблиц, полей, операций вставки, селекта и тп. В этом смысле вроде бы подход уже нормальный. Хотя изначально всё  действительно было свалено в одну кучу.
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0577 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.