La operación Crossthread no es válida … – VB.NET

Estoy usando vb.net, y en mi progtwig obtengo este error de “operación no válida de crossthread” cuando ejecuto mi backgroundworker que hará que este cuadro de texto habilitado sea verdadero. Mi sub principal primero convertirá el habilitado en falso, y cuando el backgroundworker se ejecute, lo volverá verdadero y luego saldrá. ¿Por qué me da un error? FYI: Hay más código para esto, pero no quiero que sea más confuso …

Aquí está el rastro de la stack:

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) 

y aquí está el mensaje de error exacto:

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

¡Puede alguien ayudarme!

Gracias,

Kevin

El objective de la clase BackgroundWorker es realizar trabajos en un subproceso que no sea de la GUI mientras la GUI sigue siendo receptiva. A menos que establezca Control.CheckForIllegalCrossThreadCalls en false (que no debería hacer), o use Invoke como se sugiere en las otras respuestas (que tampoco recomendaría), obtendrá una excepción de operación de cruce de hilos ilegal.

Si desea que suceda algo relacionado con la GUI mientras se ejecuta su BackgroundWorker , generalmente recomendaría usar el método BackgroundWorker.ReportProgress y adjuntar un controlador apropiado al evento BackgroundWorker.ProgressChanged . Si desea que suceda algo en la GUI una vez que finalice BackgroundWorker , simplemente conecte su controlador para actualizar la GUI al evento BackgroundWorker.RunWorkerCompleted .

¿Dónde exactamente configuras la propiedad Enabled ? Si lo hace dentro del controlador de eventos DoWork , este código se ejecuta en un hilo diferente al que se creó en el botón, lo que debería dar la excepción que experimenta. Para evitar esto, debe usar BeginInvoke . Para mayor comodidad, podría ser envuelto en un método, así:

 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 

Ahora puede llamar a ese método de manera segura para habilitar o deshabilitar cualquier control de cualquier conversación:

 SetControlEnabled(someButton, False) 

Escriba el siguiente código en Form1_Load (o lo que sea que su formulario sea) sub:

 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False 

Soluciona todos los problemas con operaciones bloqueadas de hilos cruzados.

Una mejor forma de hacerlo en VB.NET es usar una Extension que crea un código muy atractivo para las llamadas de control cruzado de la GUI.

Simplemente agregue esta línea de código a cualquier Módulo que tenga.

  _ 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 

Ahora puede escribir el código de Control de subprocesos cruzados que tiene solo 1 línea de longitud para cualquier llamada de control.

De esta manera, digamos que quieres limpiar un ComboBox y se llama desde hilos o sin hilos que puedes usar hazlo ahora

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

¿Quieres agregar algo después de borrarlo?

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

No puede establecer directamente la propiedad de control que está en el subproceso UI desde otro subproceso. Sin embargo, se puede hacer, aquí hay un ejemplo de 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 

Su formulario Form_Load () pls escribe debajo del código. Todos sus problemas serán resueltos.

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

Sugerir usar AutomationPeer.

Por ejemplo, debajo del código ejecuta el botón Ejecutar cuando presiono la tecla F5. De forma similar, si quiere un hilo o un trabajador de fondo para llamar a un evento o función, puede usar Automation Peer. En su caso, en lugar de botón (que utilicé aquí), puede usar el cuadro de texto con su propiedad apropiada para invocar.

 '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 

Saludos RV

 CheckForIllegalCrossThreadCalls = False