Основные окна пользовательского интерфейса не обновляют элемент управления -Не допустима операция с несколькими потоками - PullRequest
1 голос
/ 22 января 2009

окей .. тут проблема

У меня есть основная форма пользовательского интерфейса, в которой есть контейнер элемента управления, в который я могу добавить элемент некоторых кнопок, а также у меня есть объект backgroundworker, который запускает список. Когда события listner запускаются, я хотел бы создать кнопку в этом контейнере управления в главной форме пользовательского интерфейса. Кажется, все работает нормально, пока я не попытаюсь добавить новый элемент управления в этот контейнер. Я получаю следующее исключение

"Операция с несколькими потоками недопустима: элемент управления 'RadMagnifier_AcceptReject' доступен из потока, отличного от потока, в котором он был создан."

код выглядит так

Private Sub Mainform_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Me.SessionTableAdapter.Fill(Me.BCSSDataSet1.Session)
    FormatColumns()
    Me.BackgroundWorker2.RunWorkerAsync()
End Sub

Private Sub BackgroundWorker2_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker2.DoWork
    Notifications()
End Sub


Private Sub Notifications()
    'Start listing for events when event is fired try to add a button to a controls container on the UI thread, and that when i get the problem
End Sub

Ответы [ 6 ]

2 голосов
/ 22 мая 2009

Если вы переместили все операции пользовательского интерфейса в метод RunWorkerCompleted, это выглядит как ошибка:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=116930 http://thedatafarm.com/devlifeblog/archive/2005/12/21/39532.aspx

Я предлагаю использовать пуленепробиваемый (псевдокод):

if(control.InvokeRequired)
  control.Invoke(Action);
else
  Action()
1 голос
/ 09 февраля 2013

Нельзя обновлять элементы пользовательского интерфейса из других потоков, кроме потока пользовательского интерфейса.

Добавьте кнопку добавить код в событие RunWorkerCompleted, поскольку оно будет запущено в потоке пользовательского интерфейса. Событие DoWork выполняется в потоке пула потоков, а не в потоке пользовательского интерфейса.

1 голос
/ 24 апреля 2009

Вы должны проверить следующую статью

http://msdn.microsoft.com/en-us/library/ms171728.aspx

и для более подробной информации читайте это

http://weblogs.asp.net/justin_rogers/pages/126345.aspx

0 голосов
/ 15 февраля 2009

Вы можете использовать Control.BeginInvoke, вызывая его в своей форме, из фонового потока, передавая delete для добавления новой кнопки.

0 голосов
/ 22 января 2009

Хм ... Когда я перемещаю процедуру уведомления в событие RunworkerCompleted, оно выдает мне ту же ошибку. Я не могу добавить кнопку в событие RunworkerCompleted напрямую, поскольку процедура уведомления ожидает события, прежде чем создавать новую кнопку.

Вот более понятный пример

Частные суб-уведомления () Dim NotificationObj As New NotificationEngine ()

    ' register a handler to listen for receive events
    AddHandler Noification.ReceiveCompleted, AddressOf NotificationReceive

    ' start the notification processor
    NotificationObj.Start()

End Sub

И затем, когда событие NotificationReceive сработает, это происходит, когда я создаю новую кнопку и добавляю ее в контейнер элементов управления в главной форме.

0 голосов
/ 22 января 2009

Вы должны использовать событие RunWorkerCompleted , поскольку оно выполняется в потоке пользовательского интерфейса. Добавление элементов управления на форму из события DoWork является неправильным, поскольку эта функция выполняется в потоке, отличном от того, который создал основную форму.

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Me.BackgroundWorker1.RunWorkerAsync()
End Sub

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Thread.Sleep(1000)
    'Do not modify the UI here!!!
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    Me.Controls.Add(New Button())
End Sub
...