好的......有问题
我有一个主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
答案 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,在你的表单上调用它,从后台线程传递一个删除来添加新按钮。