主UI窗口不更新控制 - 跨线程操作无效

时间:2009-01-22 19:01:35

标签: vb.net winforms multithreading backgroundworker

好的......有问题

我有一个主UI表单,它有一个控件容器,我可以添加一些按钮项,还有一个backgroundworker对象启动一个列表器。当列表器事件触发时,我想在主UI表单上的该控件容器中创建一个按钮。一切似乎工作正常,直到我尝试将新的控件项添加到该容器。我得到以下异常

“跨线程操作无效:控制'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 个答案:

答案 0 :(得分:2)

假设您将所有UI操作移动到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 :(得分:1)

答案 2 :(得分:1)

您无法从UI线程以外的其他线程更新UI元素。

添加按钮添加代码到RunWorkerCompleted Event,因为这将在UI线程上触发。 DoWork事件在不在UI线程上的线程池线程上运行。

答案 3 :(得分:0)

您必须使用RunWorkerCompleted事件,因为它在UI线程上执行。从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

答案 4 :(得分:0)

嗯..当我将Notification程序移到RunworkerCompleted事件中时,它给了我同样的错误。我无法直接在RunworkerCompleted事件中添加按钮,因为Notification过程在创建新按钮之前等待事件发生。

这是一个更清晰的例子

私人子通知()         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事件会触发该事件。

答案 5 :(得分:0)

你可以使用Control.BeginInvoke,在你的表单上调用它,从后台线程传递一个删除来添加新按钮。

相关问题