主 UI 窗口未更新控件 - 跨线程操作无效
好吧..这是问题
我有一个主 UI 表单,它有一个控制容器,我可以向其中添加一些按钮项,而且我还有一个启动监听器的后台工作对象。 当监听器事件触发时,我想在主 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
Ok..here is the problem
I have a main UI form that has a control container that i can add some buttons item to it,and also i have a backgroundworker object that starts up a listner. When the listner events fire, i would like to create a button in that control container on the main UI form. Everything seems to work fine until i try to add a new control item to that container. I get the following exception
"Cross-thread operation not valid: Control 'RadMagnifier_AcceptReject' accessed from a thread other than the thread it was created on."
the code flows like this
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
假设您将所有 UI 操作移至 RunWorkerCompleted 方法中,它看起来像一个错误:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=116930
http://thedatafarm.com/devlifeblog/archive/2005/12/ 21/39532.aspx
我建议使用防弹(伪代码):
Assuming you moved all UI operations into the RunWorkerCompleted method, it looks like a bug:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=116930
http://thedatafarm.com/devlifeblog/archive/2005/12/21/39532.aspx
I suggest using the bullet-proof (pseudocode):
您无法从 UI 线程以外的其他线程更新 UI 元素。
将按钮添加代码添加到 RunWorkerCompleted 事件,因为它将在 UI 线程上触发。
DoWork 事件在线程池线程上运行,而不是在 UI 线程上运行。
You cannot update UI elements from other threads other than the UI thread.
Add the button add code to RunWorkerCompleted Event, since that will be fired on the UI thread.
The DoWork event runs on a thread pool thread not on the UI thread.
您必须使用 RunWorkerCompleted 事件,因为它在 UI 线程上执行。 通过 DoWork 事件在窗体上添加控件是错误的,因为该函数是在与创建主窗体的线程不同的线程上执行的。
You have to use the RunWorkerCompleted event because it is executed on the UI thread. Adding controls on the form from the DoWork event is wrong because this function is executed on a different thread than the one that created the main form.
嗯..当我将通知过程移动到 RunworkerCompleted 事件中时,它给了我同样的错误。 我无法直接在 RunworkerCompleted 事件中添加按钮,因为通知过程是在创建新按钮之前等待事件发生。
这是一个更清晰的示例
Private Sub notifications()
DimNotificationObj As NewNotificationEngine()
然后一旦NotificationReceive事件触发,我就创建一个新按钮并将其添加到主窗体上的控件容器中。
Hmm..when i move the Notification procedure into the RunworkerCompleted event it gives me the same error. I cant add the button in the RunworkerCompleted event directly because the Notification procedure is wait for event to happen before creating the new button.
Here is a more clear example
Private Sub Notifications()
Dim NotificationObj As New NotificationEngine()
And then once the NotificationReceive event fires thats when i create a new button and add it to the controls container on the main form.
您可以使用 Control.BeginInvoke,从后台线程在表单上调用它,传递一个删除来添加新按钮。
You could use Control.BeginInvoke, calling it on your form, from the background thread, passing a deleate to add the new button.