Q1
Звучит так, будто вы пытаетесь создать слишком много элементов управления пользовательского интерфейса одновременно. Даже если память осталась, у тебя кончились ручки. Ниже приведено краткое, но довольно техническое объяснение.
Q4
Я понимаю, что пользовательский объект - это любой объект, который является частью GUI. По крайней мере, до Windows XP API пользовательского интерфейса Windows находился в USER.DLL
(одна из основных DLL, составляющих Windows). По сути, пользовательский интерфейс состоит из «окон». Все элементы управления, такие как кнопки, текстовые поля, флажки, внутренне одно и то же, а именно «окна». Чтобы создать их, вы должны вызвать функцию Win32 API CreateWindow
. Эта функция затем возвращает дескриптор созданного «окна» (элемент пользовательского интерфейса или «пользовательский объект»).
Итак, я предполагаю, что дескриптор пользовательского объекта является дескриптором, возвращаемым этой функцией. (Winforms основан на старом Win32 API и поэтому будет использовать функцию CreateWindow
.)
Q2
Действительно, вы не можете создать столько элементов управления пользовательским интерфейсом, сколько захотите. Все эти дескрипторы, полученные через CreateWindow
, должны в какой-то момент быть освобождены. В Winforms самый простой и безопасный способ сделать это - использовать блок using
или вызвать Dispose
:
using (MyForm form = new MyForm())
{
if (form.ShowDialog() == DialogResult.OK) ...
}
Как правило, все System.Windows.Forms.Control
могут быть Dispose
d и должны быть утилизированы. Иногда это делается автоматически, но вам не следует полагаться на это. Всегда Dispose
контролирует ваш пользовательский интерфейс, когда он вам больше не нужен.
Примечание по Dispose
для модальных и немодальных форм:
- Модальные формы (показаны
ShowDialog
) не автоматически выбрасываются. Вы должны сделать это самостоятельно, как показано в примере кода выше.
- Немодальные формы (показанные с
Show
) автоматически удаляются для вас, поскольку вы не можете контролировать, когда они будут закрыты пользователем. Нет необходимости явно звонить Dispose
!
1049 * Q5 *
Каждый раз, когда вы создаете объект пользовательского интерфейса, Winforms внутренне выполняет вызовы CreateWindow
. Вот как распределяются ручки. И они не освобождаются, пока не будет сделан соответствующий вызов DestroyWindow
. В Winforms этот вызов запускается с помощью метода Dispose
любого System.Windows.Forms.Control
. (Примечание. Хотя я в этом достаточно уверен, на самом деле я немного догадываюсь. Возможно, я не на 100% прав. Если взглянуть на внутренности Winforms с помощью Reflector, это откроет правду.)
Q3
Предполагая, что ваш StrategyEditor
создает огромную кучу элементов управления пользовательским интерфейсом, я не думаю, что вы можете многое сделать. Если вы не можете упростить этот элемент управления (по отношению к числу дочерних элементов управления, которые он создает), то, похоже, вы застряли в ситуации, в которой находитесь. Вы просто не можете создавать бесконечно много элементов управления пользовательского интерфейса.
Однако вы можете отслеживать, сколько StrategyEditor
с открыто одновременно (увеличивать счетчик всякий раз, когда создаете экземпляр, и уменьшать его всякий раз, когда закрываете - вы можете отслеживать последний, используя FormClosing
/ FormClosed
событие формы или метод управления Dispose
). Тогда вы можете ограничить число одновременно открытых StrategyEditor
s фиксированным числом, скажем, 5. Если предел превышен, вы можете вызвать исключение в конструкторе, чтобы больше не создавалось экземпляров. Конечно, я не могу сказать, будет ли StrategyForm
хорошо обрабатывать исключение из вашего StrategyEditor
конструктора ...
public class StrategyEditor : ...
{
public StrategyEditor()
{
InitializeComponent();
if (numberOfLiveInstances >= maximumAllowedLiveInstances)
throw ...;
// not a nice solution IMHO, but if you've no other choice...
}
}
В любом случае ограничение числа экземпляров StrategyEditor
кажется временным исправлением и не решит настоящую проблему.