2016-03-27 2 views
5

Я создаю приложение Windows Form, которое динамически создает элементы управления на основе данных, извлеченных из базы данных.VB/C# .net Динамически добавлять элементы управления с фоновым рабочим

У меня есть код, прекрасно работающий в фоновом режиме, который загружает данные из базы данных и применяет его к переменным, проблема заключается в попытке создать элементы управления с использованием этих данных, я получаю многопоточную ошибку (Дополнительная информация: операция Cross-нить не действует:. «Control flowpanelMenuRules» доступ из потока, отличного от резьбы она была создана)

Я использую событие BackgroundWorker_DoWork и код, который не является следующее:

Me.flowpanelMenuRules.Controls.Add(PanelRule(i)) 

Код предшествует простой цикл, проходящий через переменную (которая является пулькой d из базы данных) и сбора информации.

У кого-нибудь есть опыт безопасного вызова вышеуказанной строки? Я просто не могу заставить его работать на всех :(

Спасибо за помощь, я могу разместить больше кода, если это необходимо.

+0

См. Https://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than- the?rq=1 для разъяснений о том, что пошло не так. –

+0

Элементы управления не должны создаваться в фоновом потоке. Они привязаны к потоку, в котором они созданы, и должны использоваться только там. Вы должны вызвать конкретное создание и обновление элементов управления, остальное можно сделать в BGW. –

ответ

6

Моя рекомендация состоит в том, чтобы ваш BackgroundWorker просто создавал элементы управления, но не добавлял их в форму. Вместо этого верните подготовленные элементы управления в поток вызывающего/пользовательского интерфейса через событие RunWorkerCompleted. Затем добавьте элементы управления в свою форму в этот момент, возможно, в сочетании с методами SuspendLayout()/ResumeLayout().

+1

Joel - Я использовал эту идею, и она отлично работает. У меня есть фоновый рабочий, который теперь запускает мой SQL-код, чтобы извлечь информацию из базы данных в переменные, а затем использовать событие Background Worker Completed, чтобы заполнить результаты в FlowLayoutPanel. Спасибо! Раньше я использовал фоновых работников, но по какой-то причине событие Completed просто подтолкнуло меня –

1

Уроженец способ применения WinForms является использование System.Winfows.Forms.Control методы как Invoke() и InvokeRequired свойство обращающегося потока пользовательского интерфейса:

if(this.flowpanelMenuRules.InvokeRequired) 
{ 
    this.flowpanelMenuRules.Invoke(() => AddPanelRule()); 
} 
else 
{ 
    AddPanelRule(); 
} 

вы можете также использовать Dispatcher класс

Если вы уверены, что в потоке пользовательского интерфейса (например, в обработчике button.Click),.предоставляет диспетчер потоков пользовательских интерфейсов, который вы можете использовать для отправки из фоновых потоков в поток пользовательского интерфейса, как обычно.

Dispatcher.CurrentDispatcher.Invoke(() => this.flowpanelMenuRules.Controls.Add(PanelRule(i))); 
+0

Возможно, вы смешиваете VB и C#? – Camo

+0

@ Rinecamo вопрос был задан с тегом C#, и все мои примеры содержат только код C#. –

+0

'Me' - эквивалент VB' this';) – Camo