Проблема при добавлении большого количества элементов управления в форму Windows .NET (C#)

У меня есть приложение Windows Form, написанное на С#. Его работа заключается в отправке сообщений списку пользователей. Пока эти сообщения отправляются, я хотел бы отображать статус операции для каждого пользователя. Что я делаю (для каждого пользователя), так это создаю элемент управления Label и добавляю его в Panel. Это работает без проблем для небольшой группы пользователей. Когда я увеличиваю размер до 1000 или более, отладчик Visual Studio отображает следующее сообщение:

Первое исключение типа System.ComponentModel.Win32Exception в System.Windows.Forms.dll Первое исключение типа System.Reflection.TargetInvocationException в mscorlib.dll

А то приложение зависает. Любые мысли о том, что я делаю неправильно и как я могу это исправить?


person adeel825    schedule 25.09.2008    source источник


Ответы (8)


Учитывая размер, я бы подумал об отображении вашего статуса в RichTextBox.

Происходит то, что вы создаете слишком много дескрипторов, и платформа не может их все обработать.

person Austin Salonen    schedule 25.09.2008
comment
Абсолютно... adeel825, помните, что почти все в System.Windows.Forms (может быть, все) соответствует Windows API, и вы связаны его ограничениями. - person John Rudy; 26.09.2008

Вместо этого используйте DataGridView.

person Muxa    schedule 25.09.2008

Это своего рода обходной путь, но я не думаю, что ваши пользователи действительно хотят просматривать список из 1000 человек. Покажите им текущий/самый последний и сводный отчет для остальных. Или пусть пролистают.

person Joel Coehoorn    schedule 25.09.2008

Не видя конкретного кода, сложно сказать. Если бы мне поручили ту же программу, я бы подошел к ней по-другому.

Я бы использовал Grid или Listview для отображения пользователя и статуса его или ее отправляемого сообщения. Эти элементы управления могут обрабатывать неограниченное (ну, ограниченное системной памятью) количество строк. Одна строка на пользователя (или одна строка на сообщение — что лучше работает).

Это должно быть единственное, что происходит в потоке пользовательского интерфейса. Используйте фоновую рабочую роль (класс BacngroundWorker) или структуру очереди сообщений (MSMQ, SQL-сервер), чтобы сообщения отправлялись асинхронно и сообщали о состоянии резервной копии через BackgroundWorker.

Что касается вашей конкретной ошибки - я не знаю, почему вы ее получаете. Не должно быть никаких ограничений на количество меток, которые вы можете поместить на WinForm. Я подозреваю, что ошибка вызвана чем-то другим.

person CleverPatrick    schedule 25.09.2008

Вместо этого поместите ProgressBar в форму. Если вы отправляете одно сообщение 1000 человек, просто увеличивайте ProgressBar на 1 каждый раз, когда вы отправляете сообщение.

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

У вас также может быть метка для каждого индикатора выполнения (с надписью «Завершено на 95%» или «Сообщение 3 из 5» или что-то еще).

У вас не может быть такого большого количества элементов управления в форме .NET, и даже если бы вы могли, ни один пользователь не смог бы просматривать их все одновременно.

person MusiGenesis    schedule 25.09.2008

Мне нравится использовать ListView в подробном режиме. Обычно я создаю подпрограмму для добавления строки, делаю ее выделенной и вызываю EnsureVisible() для элемента для автоматической прокрутки к нему.

Как уже упоминалось, элементы управления соотносятся с одним или несколькими дескрипторами окон, и ОС может выдавать только их количество.

person spoulson    schedule 25.09.2008

Слишком много контроля! Создайте единый элемент управления, чтобы содержать все эти сообщения о состоянии. Как насчет многострочного текстового поля?

person Matt Howells    schedule 25.09.2008

Если вы буквально показываете только метки на панели, я бы посоветовал вам отображать статусы с помощью GDI. Напишите текст видимой области в OnPaint и аннулируйте область метки состояния только при ее изменении.

person BlackWasp    schedule 25.09.2008