Модераторы: 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   Вверх
N1ko
Дата 27.5.2010, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



А можно ли как то более точно отследить на каком этапе у меня создаются дескрипторы, нежели запускать програму и смотреть на диспетчер? 
PM MAIL ICQ   Вверх
mihryak
Дата 27.5.2010, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



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


Опытный
**


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

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



Вот за это Вам огромное спасибо. Действительно помогло. Утечка идёт от String как я и предполагал. Насколько я понимаю string - ом должен занимаеться сборщик мусора автоматически. Но судя по всему он этого делать не успевает. Можно ли как то вучную это делать? String.Empty не помагает поскольку судя по всему из памяти строка не удаляется.

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

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



вот бы код рекурсии увидеть)...

Добавлено через 2 минуты и 28 секунд
Конец жизни переменной:
 - до конца области видимости в Debug
 - до последнего упоминания ее в коде в Release
http://forum.vingrad.ru/forum/topic-301328.html ©


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
N1ko
Дата 31.5.2010, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



uranpro ,вот собственно рекурсия. Метод ScanDbfFiles сканирует заданую папку на наличие в ней ДБФ файлов. Если таковые там есть, откурывается ДБФ соединение и с читывается вся инфа с файлов. Второй метод ScanFolder сканирует папку на наличие в ней других папок.

 
Код

private void ScanDbfFiles(string PrmPath)
        {
            dbfDir = new DBFolder(PrmPath); \\ класс DBFolder  - обёртка для папки, в котором хранятся ДБФ файлы
            DirectoryInfo _selectedDir = new DirectoryInfo(PrmPath);
            fiDirectoryFile = _selectedDir.GetFiles("*.dbf");
            if (fiDirectoryFile.Length != 0)
            {
                dbfDir.OpenConnection();
                sqLiteDB.OpenConnection(); \\ sqLiteDB - обёртка для реализации СУБД
                sqLiteDB.StartInsertProcess();
                foreach (FileInfo _file in fiDirectoryFile)
                {
                    using (DBFile _currDbf = new DBFile(_file, dbfDir.DBFConnection, sqLiteDB.Tables)) \\ DBFile - класс хранящий мнфу о ДБФ файле
                    {
                        if (_currDbf.Type != DBFTypes.Unknown)
                        {
                            if (!sqLiteDB.Tables[_currDbf.Type.GetHashCode()].InsertProvider.InsertFromDbf(_currDbf))
                            {
                                frmLBLog.Invoke(new DelAddItemToLog(AddItemToLog), _currDbf);
                            }
                        }
                        DBFCounter.SubFromSize(_file.Length); - DBFCounter - статический класс, который хранит инфу об общем объёме ДБФ файлов и о объёме уже просканированых фалов
                        this.frmBGVReport.ReportProgress(DBFCounter.Progress);
                    }
                }
                sqLiteDB.CommitInsertProcess();
                sqLiteDB.CloseConnection();
                dbfDir.CloseConnection();
            }
        }
        public void ScanFolder(string Path)
        {
            DirectoryInfo _currentFolder = new DirectoryInfo(Path);
            ScanDbfFiles(Path);
            DirectoryInfo[] SubSelectedDir = _currentFolder.GetDirectories();
            for (int i = 0; i < SubSelectedDir.Length; ++i)
            {
                ScanFolder(SubSelectedDir[i].FullName);
            }
        }



Вот такая вот реализация рекурсии...

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


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


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

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



N1ko, 
используйте перегруженный метод DirectoryInfo.GetFiles(String, SearchOption), где SearchOption есть перечисление, характеризующее, искать ли файл в текущем каталоге, или еще и во вложенных.
Типа этого:
Код

//...
fiDirectoryFile = _selectedDir.GetFiles("*.dbf", SearchOption.AllDirectories);
//...


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


Опытный
**


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

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



Если так делать, возникают дополнительные сложности. Ну допустим просканим мы таким способом заданную папку, соответственно ссылки на все файлы будут находиться в одном хранилище и их будет очень много. Для того что бы прочитать ДБФ файл нужно открыть соединение с папкой, в которой он находится. А допустим таких фалов 20 и они распологаются не подряд. Тогда нам прийдётся создавать и открывать несколько раз одно и то же самое соединение. При преходе к каждому новому файлу прийдётся сверять его месторасположение по сравнению с предыдущим и тп. Считаю что проще будет всё таки рекурсией всё сделать. И в основе перегруженного метода с двумя параметраме наверняка используюется всё та же рекурсия. Хотя в этом и не особо уверен.

Это сообщение отредактировал(а) N1ko - 31.5.2010, 11:37
PM MAIL ICQ   Вверх
PashaPash
Дата 1.6.2010, 07:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



N1ko, так сгруппируй результаты поиска по Path.GetDirectory
Код

            string[] files = Directory.GetFiles("<path>", "*.dbf", SearchOption.AllDirectories);
            var filesByDirectory = files.GroupBy(f => Path.GetDirectoryName(f)).ToList();

            foreach (var directory in filesByDirectory)
            {
                Console.WriteLine(directory.Key);
                // открыть соединение с directory.Key, пройтись по файлам-таблицам - foreach (string file in directory)
            }



--------------------
PM MAIL WWW   Вверх
PashaPash
Дата 1.6.2010, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



N1ko, кстати, а где в первом примере ты открываешь и закрываешь соединение? 


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


Опытный
**


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

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



Во втором примере как раз видно что открываю я соединенеие перед использованием функции InsertFromDbf
 
Код

dbfDir.OpenConnection();
 sqLiteDB.OpenConnection(); \\ sqLiteDB - обёртка для реализации СУБД

 и сооответственно закрываю его после её завершения.
Код

sqLiteDB.CloseConnection();
dbfDir.CloseConnection();

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

Это сообщение отредактировал(а) N1ko - 1.6.2010, 12:42
PM MAIL ICQ   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

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


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

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


 




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


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

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