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
我有一个主UI表单,有一个控件容器,我可以添加一些按钮项目,我还有一个backgroundworker对象,启动一个列表器。当列表器事件触发时,我想在主UI表单上的该控件容器中创建一个按钮。在尝试向该容器添加新控件项之前,一切似乎都能正常工作。我得到以下异常
"Cross-thread operation not valid: Control 'RadMagnifier_AcceptReject' accessed from a thread other than the thread it was created on."
“跨线程操作无效:控制'RadMagnifier_AcceptReject'从其创建的线程以外的线程访问。”
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
6 个解决方案
#1
Assuming you moved all UI operations into the RunWorkerCompleted method, it looks like a bug:
假设您将所有UI操作移动到RunWorkerCompleted方法中,它看起来像一个错误:
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):
我建议使用防弹(伪代码):
if(control.InvokeRequired)
control.Invoke(Action);
else
Action()
#2
You should check out the follow article
你应该看看以下文章
http://msdn.microsoft.com/en-us/library/ms171728.aspx
and for more in-depth information read this
而对于更深入的信息,请阅读此内容
#3
You cannot update UI elements from other threads other than the UI thread.
您无法从UI线程以外的其他线程更新UI元素。
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 Event,因为这将在UI线程上触发。 DoWork事件在不在UI线程上的线程池线程上运行。
#4
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事件,因为它在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
#5
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.
嗯..当我将通知程序移动到RunworkerCompleted事件时,它给了我同样的错误。我无法直接在RunworkerCompleted事件中添加按钮,因为Notification过程在创建新按钮之前等待事件发生。
Here is a more clear example
这是一个更清晰的例子
Private Sub Notifications() Dim NotificationObj As New NotificationEngine()
私有子通知()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
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.
然后,当我创建一个新按钮并将其添加到主窗体上的控件容器时,NotificationReceive事件会触发该事件。
#6
You could use Control.BeginInvoke, calling it on your form, from the background thread, passing a deleate to add the new button.
你可以使用Control.BeginInvoke,在你的表单上调用它,从后台线程传递一个删除来添加新按钮。
#1
Assuming you moved all UI operations into the RunWorkerCompleted method, it looks like a bug:
假设您将所有UI操作移动到RunWorkerCompleted方法中,它看起来像一个错误:
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):
我建议使用防弹(伪代码):
if(control.InvokeRequired)
control.Invoke(Action);
else
Action()
#2
You should check out the follow article
你应该看看以下文章
http://msdn.microsoft.com/en-us/library/ms171728.aspx
and for more in-depth information read this
而对于更深入的信息,请阅读此内容
#3
You cannot update UI elements from other threads other than the UI thread.
您无法从UI线程以外的其他线程更新UI元素。
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 Event,因为这将在UI线程上触发。 DoWork事件在不在UI线程上的线程池线程上运行。
#4
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事件,因为它在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
#5
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.
嗯..当我将通知程序移动到RunworkerCompleted事件时,它给了我同样的错误。我无法直接在RunworkerCompleted事件中添加按钮,因为Notification过程在创建新按钮之前等待事件发生。
Here is a more clear example
这是一个更清晰的例子
Private Sub Notifications() Dim NotificationObj As New NotificationEngine()
私有子通知()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
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.
然后,当我创建一个新按钮并将其添加到主窗体上的控件容器时,NotificationReceive事件会触发该事件。
#6
You could use Control.BeginInvoke, calling it on your form, from the background thread, passing a deleate to add the new button.
你可以使用Control.BeginInvoke,在你的表单上调用它,从后台线程传递一个删除来添加新按钮。