none
Ошибка при создании дескриптора окна. RRS feed

  • Вопрос

  • Доброго времени суток!

    Вопрос к понимающим...

    VB 2010 Express: Есть процедура, которая  производит заполнение панели (Panel) пользовательскими элементами управления (Control) - т.е. создает некий интерфейс. Процедура вызывается по запросу пользователя.  При большом количестве добавляемых Contol возникает Win32Exeption: "Ошибка при создании дескриптора окна".  Явно отследить, в каком месте кода возникает исключение, или невозможно ("Нет доступных исходных файлов") или VB "привязывает" исключение к разным местам кода. У меня есть такое подозрение, что "где-то что-то переполняется", т.к. при вызове процедуры с постоянным кол-вом добавляемых Control, исключение возникает при определенном числе раз вызова процедуры. Тоже самое происходит в скомпилированном EXE-файле. Буду очень признателен, если кто-нибудь подскажет чем это может быть вызвано. Спасибо.

    13 августа 2014 г. 20:00

Ответы

  • Хм. А перед добавлением новых Control, вызов метода Controls.Clear для Panel (в которую добавляются Control) - это неправильно? т.е. Panel надо чистить циклом Control.Dispose?

    Метод Clear просто очищает коллекцию Controls. Сами контролы продолжают висеть в памяти до очередной сборки мусора.

    Может подскажите, а если добавляемая Panel, не будет содержать Control, а в Panel необходимые элементы рисовать через GreateGraphics - это улучшит ситуацию?

    Может улучшить, может ухудшить. Смотря как рисовать будете. Вот полезная ссылка: Преодолевая границы Windows: объекты USER и GDI (часть 2). Общее количество дескрипторов не должно превышать 10000, а в их число входят и кисти, и перья, так что рисуя вручную тоже можно насоздавать (и не удалить) кучу дескрипторов.

    Попробовал чистить родительскую Panel циклом - разницы не заметил. Может надо ка-то по-хитрому?

    Нужно диспозить все контролы в коллеции panel.Controls, а также рекурсивно в коллекциях самих этих контролов. В частности, если используются UserControl, то у них.

    15 августа 2014 г. 13:10

Все ответы

  • Ну у вас верные подозрения. Проблема в переполнении, но вот без кода понять что именно его вызывать не получится

    VB.Net - WPF, WinRT, WP

    14 августа 2014 г. 11:06
    Отвечающий
  • Ну у вас верные подозрения. Проблема в переполнении, но вот без кода понять что именно его вызывать не получится

    VB.Net - WPF, WinRT, WP

    В процедуре, Control создаются программно. Попробовал сделать UserControl и "плодить" их - ситуация улучшилась. Отсюда такой вопрос: а может происходить исключение из-за того, что все добавления Control и прочие расчеты (достаточно емкие) управляются одним кодом (в коде одной формы). Я не спец, но может ёмкие расчеты и процедуры создания/добавления Control нужно как-то разводить по разным потокам? (Т.е. перерисовки и прочие вычисления UserControl происходят в отдельном потоке или в том же, что и все процедуры основного кода программы?)

    Код, обрабатывает данные стороннего продукта, по-этому и вопросы задаю "теоретические". Хотя, если сможете не запуская код, сказать "где собака порылась" - могу Вам выслать (скажите - куда).



    • Изменено alexusm 15 августа 2014 г. 8:06
    15 августа 2014 г. 7:50
  • Разбивка на потоки нужна когда длительная процедура вешает основной поток, то есть пока выполняется емкий код, форма просто "висит".

    У вас же судя по описанию другая ситуация и замена Control на UserControl, та как последний менее емкий.

    Как много контролов вы добавляете на форму?


    VB.Net - WPF, WinRT, WP

    15 августа 2014 г. 8:21
    Отвечающий
  • Когда ранее созданные контролы становятся не нужны, обязательно удаляйте их с помощью вызова Dispose. Это решит проблему.
    15 августа 2014 г. 10:00
  • Как много контролов вы добавляете на форму?


    VB.Net - WPF, WinRT, WP

    Смотря как считать (не знаю как правильно): грубо говоря, ошибка возникает при добавлении 40+ Panel, содержащих, примерно, 60 других Control (CheckBox и Label).
    15 августа 2014 г. 11:33
  • Когда ранее созданные контролы становятся не нужны, обязательно удаляйте их с помощью вызова Dispose. Это решит проблему.
    Хм. А перед добавлением новых Control, вызов метода Controls.Clear для Panel (в которую добавляются Control) - это неправильно? т.е. Panel надо чистить циклом Control.Dispose?

    • Изменено alexusm 15 августа 2014 г. 11:44
    15 августа 2014 г. 11:39
  • Когда ранее созданные контролы становятся не нужны, обязательно удаляйте их с помощью вызова Dispose. Это решит проблему.

    Хм. А перед добавлением новых Control, вызов метода Clear для Panel (в которую добавляются Control) - это неправильно? т.е. Panel надо чистить циклом Control.Dispose?

    Dispose предлагается вызывать при удалении неиспользуемых Panel/Control, но у вас я так понимаю проблема возникает еще до этого.

    Скорее всего ваши Control тяжеловесны и на все их количество банально не хватает оперативки.

    Уверен, что на машине по мощнее можно будет добавить чуть больше элементов, но потом то же выскочит эта проблема.

    Это судя по всему вопрос оптимизации, с которым я в WinForms не сталкивался.


    VB.Net - WPF, WinRT, WP

    15 августа 2014 г. 11:44
    Отвечающий
  •  т.е. Panel надо чистить циклом Control.Dispose?


    Попробовал чистить родительскую Panel циклом - разницы не заметил. Может надо ка-то по-хитрому?


    15 августа 2014 г. 12:18
  • вопрос оптимизации...


    VB.Net - WPF, WinRT, WP

    Может подскажите, а если добавляемая Panel, не будет содержать Control, а в Panel необходимые элементы рисовать через GreateGraphics - это улучшит ситуацию?
    15 августа 2014 г. 12:22
  • Может подскажите, а если добавляемая Panel, не будет содержать Control, а в Panel необходимые элементы рисовать через GreateGraphics - это улучшит ситуацию?
    Теоретически да. Ведь что такое Control/UserControl? Это класс с набором свойств и параметров, половина из которых в вашем случае может и не нужны.

    VB.Net - WPF, WinRT, WP

    15 августа 2014 г. 12:27
    Отвечающий
  • Хм. А перед добавлением новых Control, вызов метода Controls.Clear для Panel (в которую добавляются Control) - это неправильно? т.е. Panel надо чистить циклом Control.Dispose?

    Метод Clear просто очищает коллекцию Controls. Сами контролы продолжают висеть в памяти до очередной сборки мусора.

    Может подскажите, а если добавляемая Panel, не будет содержать Control, а в Panel необходимые элементы рисовать через GreateGraphics - это улучшит ситуацию?

    Может улучшить, может ухудшить. Смотря как рисовать будете. Вот полезная ссылка: Преодолевая границы Windows: объекты USER и GDI (часть 2). Общее количество дескрипторов не должно превышать 10000, а в их число входят и кисти, и перья, так что рисуя вручную тоже можно насоздавать (и не удалить) кучу дескрипторов.

    Попробовал чистить родительскую Panel циклом - разницы не заметил. Может надо ка-то по-хитрому?

    Нужно диспозить все контролы в коллеции panel.Controls, а также рекурсивно в коллекциях самих этих контролов. В частности, если используются UserControl, то у них.

    15 августа 2014 г. 13:10