Operação de Crossthread inválida… – VB.NET

Eu estou usando vb.net, e no meu programa eu recebo este erro ‘crossthread operação não válida’ quando eu executar meu backgroundworker que irá tornar esta checkbox de texto habilitada true. Meu sub principal primeiro irá ativar o enabled para false, e quando o backgroundworker for executado, ele retornará true e sairá. Por que isso me dá um erro? FYI: Há mais código para isso, mas eu não quero deixar isso mais confuso …

Aqui está o rastreamento de pilha:

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) 

e aqui está a mensagem de erro exata:

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

Alguém por favor pode me ajudar!

Obrigado,

KEvin

O objective da class BackgroundWorker é executar o trabalho em um thread não-GUI enquanto a GUI permanece responsiva. A menos que você defina Control.CheckForIllegalCrossThreadCalls como false (o que você não deveria fazer), ou use Invoke como sugerido nas outras respostas (o que eu também não recomendaria), você obterá uma exceção ilegal de operação cross-thread.

Se você quiser que “coisas” relacionadas à GUI aconteçam enquanto o BackgroundWorker estiver em execução, geralmente recomendo usar o método BackgroundWorker.ReportProgress e append um manipulador apropriado ao evento BackgroundWorker.ProgressChanged . Se você quiser que algo na GUI aconteça depois que o BackgroundWorker for concluído , simplesmente anexe seu manipulador para atualizar a GUI para o evento BackgroundWorker.RunWorkerCompleted .

Onde exatamente você define a propriedade Enabled ? Se você fizer isso no manipulador de events DoWork , esse código estará sendo executado em um thread diferente daquele em que o botão foi criado, o que deve dar a exceção que você enfrenta. Para contornar isso, você deve usar o BeginInvoke . Por conveniência, poderia ser envolvido em um método, da seguinte forma:

 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 

Agora você pode chamar com segurança esse método para ativar ou desativar qualquer controle de qualquer segmento:

 SetControlEnabled(someButton, False) 

Digite o seguinte código no Form1_Load (ou seja qual for o seu formulário):

 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False 

Ele corrige todos os problemas com operações de encadeamento cruzado.

Melhor maneira para isso em VB.NET é usar uma Extension que torna muito bonito código procurando para chamadas de controle GUI cross-threading.

Basta adicionar esta linha de código a qualquer módulo que você tenha.

  _ 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 

Agora você pode escrever o código de controle de thread cruzado com apenas 1 linha de comprimento para qualquer chamada de controle.

Assim, digamos que você deseja limpar um ComboBox e é chamado a partir de threads ou sem threads que você pode apenas usar fazer isso agora

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

Quer adicionar algo depois de limpá-lo?

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

Você não pode definir diretamente a propriedade de um controle que está no thread de interface do usuário de outro thread. Isso pode ser feito, aqui está um exemplo do 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 

Seu Form_Load () pls escreve abaixo parte do código. Todos os seus problemas serão resolvidos.

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

Sugira usar o AutomationPeer.

Por exemplo abaixo do código chama o botão Execute quando pressiono a tecla F5. Da mesma forma, se você quiser que um thread ou Worker em segundo plano chame um evento ou function, você pode usar o Automation Peer. No seu caso, em vez de botão (que eu usei aqui), você pode usar checkbox de texto com sua propriedade apropriada 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 

Atenciosamente RV

 CheckForIllegalCrossThreadCalls = False