Подтвердить что ты не робот

Успешное завершение операции

У меня есть пользовательский метод, который находит наибольший размер для использования для данной строки и шрифта, чтобы заполнить данный ящик, не отрезав текст. Чтобы протестировать его, я создал службу, которая циклически проходит несколько строк и несколько разных шрифтов и делает их в цикле Parallel.For. Когда эта служба запущена, все ядра ЦП в системе находятся на уровне 90% 100. После запуска в течение 8 или 9 часов он начнет бросать исключения. Он по-прежнему будет работать большую часть времени, но будут случайные исключения или всплески исключений.

В самом внутреннем исключении есть сообщение "Операция завершена успешно" и происходит из AccessorWidthIncludingTrailingWhitespace в объекте FormattedText. Стек вызова выглядит следующим образом:

   at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d)
   at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
   at System.Windows.Threading.Dispatcher..ctor()
   at System.Windows.Threading.Dispatcher.get_CurrentDispatcher()
   at System.Windows.Media.TextFormatting.TextFormatter.FromCurrentDispatcher(TextFormattingMode textFormattingMode)
   at System.Windows.Media.FormattedText.LineEnumerator..ctor(FormattedText text)
   at System.Windows.Media.FormattedText.DrawAndCalculateMetrics(DrawingContext dc, Point drawingOffset, Boolean getBlackBoxMetrics)
   at System.Windows.Media.FormattedText.get_Metrics()
   at System.Windows.Media.FormattedText.get_WidthIncludingTrailingWhitespace()
   ...My Library Here...

При исследовании этого я обнаружил, что для него нередко используются неизолированные объекты рисования (Graphics, Icons и т.д.), но я не мог найти используемые одноразовые объекты. Код размера текста использует классы WPF (FontFamily, FormattedText и Typeface), и ни один из них не реализует IDisposable.

У меня есть perfmon, контролирующий процесс, и в то время как использование памяти, количество обработчиков и количество потоков меняются довольно сильно, они никогда не выходят из-под контроля. Это говорит мне, что это, вероятно, не утечка дескриптора. Что еще может быть?

UPDATE: я провел тест уже несколько дней с одним существенным изменением: он выполняет регулярную замену вместо параллельной. Он еще не разбился, и перфмон показывает горизонтальные линии с очень небольшим изменением. Возможно, это проблема с распараллеливанием, а не с текстом WPF?

4b9b3361

Ответ 1

Похоже, что исключение было создано, когда WPF попытался выделить собственный дескриптор окна Win32 для другого нового диспетчера. Возможно, вы достигли максимального количества ручек для вашего процесса?

Вы пытались принудительно собрать мусор на каждой итерации? Большинство классов WPF не реализуют IDisposable, но они по-прежнему используют неуправляемые ресурсы, которые управляются внутри WPF.

Есть другой способ переполнения, который я могу себе представить. Свойство CurrentDispatcher создает новый диспетчер для каждого потока. Каждый диспетчер никогда не останавливается, пока не будет вызван InvokeShutdown. Таким образом, поток, в котором работает Диспетчер, никогда не будет прерван, потому что нет окна, и никто не должен нажать кнопку "Закрыть". Возможно, это заставляет Parallel.For реализации выделять новый Thread для следующей итерации, в которой также нужен еще один новый диспетчер и еще один новый дескриптор. К сожалению, у меня нет большого опыта использования Parallel, поэтому это только предположение.