.NET 2.0 ThreadPool Увеличение стека потоков вызывает исключение нехватки памяти (достигнут предел фиксации)

ОС: Windows 7 Embedded

Оперативная память: 1 ГБ

Размер файла подкачки: 500 МБ

Оставшееся дисковое пространство: ~1 ГБ

.NET: 2.0

Я работаю над приложением.NET 2.0 Winforms, написанным на C#, которое работает на Windows 7 Embedded, где в системе всего 1 ГБ ОЗУ и довольно ограниченное свободное дисковое пространство (~1 ГБ). Мы переходим на Windows 7 Embedded с Windows XP Embedded, и хотя наша программа хорошо работает на Windows XP, она несколько раз выходила из строя из-за нехватки памяти в Windows 7. После сбоев мы добавили файл подкачки объемом 500 МБ (По умолчанию для Windows 7 Embedded используется размер файла подкачки, равный 0 МБ). Однако, поскольку мы сузили исключение нехватки памяти, вызванное увеличением выделенной памяти программы, возможно, что предел системного принятия будет достигнут в течение достаточно продолжительных периодов времени, даже с файлом подкачки. Мы не можем быстро перенести наше оборудование на что-то более подходящее и должны найти программное решение, которое может решить эту проблему до следующего выпуска.

Используя инструмент SysInternals VMMap, мы видим, что количество стеков потоков в виртуальной памяти программы медленно увеличивается с течением времени, что в конечном итоге приводит к сбою, когда зафиксированная память программы приводит к тому, что система превышает свой предел фиксации. Причина увеличения стека потоков была изолирована в.NET 2.0 ThreadPool, который по какой-то причине создает чистое положительное число потоков с течением времени. Мы думаем, что это происходит из-за чрезмерного использования класса System.Timers.Timer в нашем коде, когда каждый экземпляр запускает свой обработчик прошедшего таймера события в ThreadPool, хотя до сих пор не ясно, почему ThreadPool хранит так много потоков, даже когда предполагается, что они не всегда используются обратными вызовами таймера. Некоторые из этих обработчиков событий обрабатывают информацию дольше, чем было бы идеально для потока ThreadPool, при этом худшие нарушители даже вызывают Thread.Sleep().

Мы придумали несколько возможных решений этой проблемы, включая ограничение количества рабочих потоков ThreadPool, замену более длительных обратных вызовов таймера для потоков и переход на более высокую версию.NET. Последнее решение предполагает, что оптимизация диспетчера ThreadPool была выполнена в течение итераций.NET, что может помочь облегчить проблему. Существуют ли другие очевидные (или неочевидные) решения, которые мы пропустили?

Изменить: При дальнейшей проверке потоки ThreadPool, которые генерируются и остаются, имеют следующий стек вызовов:

ntdll!KiFastSystemCallRet 
ntdll!ZwWaitForSingleObject+c 
KERNELBASE!WaitForSingleObjectEx+98 
kernel32!WaitForSingleObjectExImplementation+75 
mscorwks!PEImage::LoadImage+1af 
mscorwks!CLREvent::WaitEx+117 
mscorwks!CLREvent::Wait+17 
mscorwks!ThreadpoolMgr::SafeWait+73 
mscorwks!ThreadpoolMgr::WorkerThreadStart+11c 
mscorwks!Thread::intermediateThreadProc+49 
kernel32!BaseThreadInitThunk+e 
ntdll!__RtlUserThreadStart+70 
ntdll!_RtlUserThreadStart+1b 

0 ответов

Другие вопросы по тегам