Исключение System.OutOfMemory пула потоков при выполнении задания SQL - PullRequest
1 голос
/ 30 июня 2011

Я продолжаю получать исключение System.OutOfMemory в моем приложении WinForms, которое выбрасывается при выполнении обновления SQL, я думаю. Как я могу это исправить? В данном случае я использую SQLEXPRESS, пробую код на 32-битной машине, чтобы при запуске ThreadPool имел 1023 рабочих потока по умолчанию.

MyClass myClass = new MyClass();

for (int i = 0; i < 1000000; i++)
{              
    ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), myClass);
}

private void Foo(object state)
{
    //Some Stuff and SQL UPDATE
}

Когда приложение запускается, ThreadPool начинается с 8 потоков и начинает увеличивать выделенный номер потока для выполнения задания. Через некоторое время, например, он достигает 200 потоков и больше не может его обрабатывать, выдает исключение System.OutOfMemory. Когда я проверяю трассировку стека, я вижу, что исключение происходит в операции SQL метода. Что я должен делать? Нужно ли увеличивать размер буфера в моей базе данных? Я не хочу ограничивать максимальный размер ThreadPools или пытаться использовать Thread.Sleep () для более медленных и менее частых запросов к БД.

1 Ответ

2 голосов
/ 30 июня 2011

Слепое создание большого количества потоков, чтобы ускорить выполнение операции, не является хорошим решением и почти никогда не работает (за исключением, к счастью, возможно). Имейте в виду, что каждому потоку выделяется свой собственный стек, который по умолчанию составляет 1 МБ. Так что в случае, если вы получите 1000 потоков, которые будут использовать 1 ГБ ОЗУ, как это.

Если вы нажмете на БД, то параллельная работа с большой вероятностью будет ограничена дисковым вводом / выводом, поэтому использование большего количества потоков может даже ухудшить ситуацию.

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

В зависимости от ваших операций SQL вы можете столкнуться с проблемой фрагментации кучи больших объектов. Объекты размером более 85 000 байт помещаются в LOH, который не сжимается, и вы можете столкнуться с неожиданными исключениями OOM. Поэтому проверьте, создаете ли вы большие массивы или списки объектов.

В противном случае: Используйте средства отладки для Windows , чтобы создать дамп памяти и посмотреть, какие объекты у вас есть, и где хранятся ссылки, чтобы сохранить их живыми. В качестве альтернативы вы можете использовать профилировщик памяти .NET, но большинство действительно полезных не бесплатны (однако обычно они идут с оценочным периодом X дней).

...