Crossthread operation not valid… - VB.NET

匿名 (未验证) 提交于 2019-12-03 01:18:02

问题:

I am using vb.net, and in my program I get this 'crossthread operation not valid' error when I run my backgroundworker that will make this textbox enabled true. My main sub will first turn the enabled to false, and when the backgroundworker runs it will turn it back true then exit. Why does it give me an error? FYI: There is more code to this but I don't want to make it any more confusing...

Here is the stack trace:

at System.Windows.Forms.Control.get_Handle()    at System.Windows.Forms.Control.OnEnabledChanged(EventArgs e)    at System.Windows.Forms.Control.set_Enabled(Boolean value)    at Helium.Form1.BackgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in C:\Users\Kevin\documents\visual studio 2010\Projects\Helium\Helium\Form1.vb:line 167    at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)    at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument) 

and here is the exact error message:

{"Cross-thread operation not valid: Control 'mainText' accessed from a thread other than the thread it was created on."} 

Can someone please help me out!

Thanks,

KEvin

回答1:

The purpose of the BackgroundWorker class is to perform work on a non-GUI thread while the GUI remains responsive. Unless you set Control.CheckForIllegalCrossThreadCalls to false (which you shouldn't do), or use Invoke as suggested in the other answers (which I also wouldn't recommend), you're going to get an illegal cross-thread operation exception.

If you want GUI-related "stuff" to happen while your BackgroundWorker is running, I'd generally recommend using the BackgroundWorker.ReportProgress method and attaching an appropriate handler to the BackgroundWorker.ProgressChanged event. If you want something on the GUI to happen once the BackgroundWorker is finished, then simply attach your handler to update the GUI to the BackgroundWorker.RunWorkerCompleted event.



回答2:

Type the following code in the Form1_Load (or whatever your form is) sub:

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False 

It fixes all problems with blocked cross-thread operations.



回答3:

Where exactly do you set the Enabled property? If you do it within the DoWork event handler, this code is running on a different thread than the button was created on, which should give the exception that you experience. To get around this, you should use BeginInvoke. For convenience it could be wrapped into a method, like so:

Private Sub SetControlEnabled(ByVal ctl As Control, ByVal enabled As Boolean)     If ctl.InvokeRequired Then         ctl.BeginInvoke(New Action(Of Control, Boolean)(AddressOf SetControlEnabled), ctl, enabled)     Else         ctl.Enabled = enabled     End If End Sub 

Now you can safely call that method to enable or disable any control from any thread:

SetControlEnabled(someButton, False) 


回答4:

Better way to this in VB.NET is to use a Extension it makes very nice looking code for cross-threading GUI Control Calls.

Just add this line of code to any Module you have.

 _ Public Sub Invoke(ByVal control As Control, ByVal action As Action)     If control.InvokeRequired Then         control.Invoke(New MethodInvoker(Sub() action()), Nothing)     Else         action.Invoke()     End If End Sub 

Now you can write Cross-Thread Control code that's only 1 line long for any control call.

Like this, lets say you want to clear a ComboBox and it's called from threads or without threads you can just use do this now

cboServerList.Invoke(Sub() cboServerList.Items.Clear()) 

Want to add something after you clear it?

cboServerList.Invoke(Sub() cboServerList.Items.Add("Hello World")) 


回答5:

You cannot directly set a control's property that is on the UI thread from another thread. It can be done though, here is an example from msdn.

Private Sub SetText(ByVal [text] As String)      ' InvokeRequired required compares the thread ID of the'     ' calling thread to the thread ID of the creating thread.'     ' If these threads are different, it returns true.'     If Me.textBox1.InvokeRequired Then         Dim d As New SetTextCallback(AddressOf SetText)         Me.Invoke(d, New Object() {[text]})     Else         Me.textBox1.Text = [text]     End If End Sub 


回答6:

Your Form_Load () pls write below code part. All your problems will be solved.

'## crossed-thread parts will not be controlled by this option...  System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False 


回答7:

Suggest to use AutomationPeer.

For example below code calls Execute button when I press F5 key. Similarly if you want a thread or Background worker to call an event or function you can use Automation Peer. In your case instead of button (Which I used here) you can use text box with its appropriate property to invoke.

'Button name=btnExecute  'Imports System.Windows.Automation.Peers  'Imports System.Windows.Automation.Provider  If e.Key = Key.F5 Then     Dim peer As New ButtonAutomationPeer(btnExecute)     Dim invokeProv As IInvokeProvider = TryCast(peer.GetPattern(PatternInterface.Invoke), IInvokeProvider)     invokeProv.Invoke()  End If 

Regards RV



回答8:

CheckForIllegalCrossThreadCalls = False 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!