Crossthread-Operation nicht gültig … – VB.NET

Ich benutze vb.net, und in meinem Programm erhalte ich den Fehler “Crossthread-Operation nicht gültig”, wenn ich meinen Hintergrundarbeiter starte, der dieses Textfeld aktiviert. Mein Haupt-Sub wird zuerst die Aktivierung zu false machen, und wenn der Hintergrundarbeiter läuft, wird es wieder auf True und dann auf Exit gesetzt. Warum gibt es mir einen Fehler? Zu Ihrer Information: Es gibt mehr Code dazu, aber ich möchte es nicht noch verwirrender machen …

Hier ist der 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) 

und hier ist die genaue Fehlermeldung:

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

Kann mir bitte jemand helfen!

Vielen Dank,

Kevin

   

Der Zweck der BackgroundWorker class ist die Ausführung von Arbeiten an einem nicht GUI- Thread, während die GUI reaktionsfähig bleibt. Wenn Sie Control.CheckForIllegalCrossThreadCalls auf false (was Sie nicht tun sollten) oder Invoke wie in den anderen Antworten vorgeschlagen (was ich auch nicht empfehlen würde), erhalten Sie eine Ausnahme für eine unzulässige Cross-Thread-Operation.

Wenn Sie möchten, dass GUI-bezogene “Sachen” passieren, während Ihr BackgroundWorker wird, würde ich im Allgemeinen empfehlen, die BackgroundWorker.ReportProgress Methode zu verwenden und einen entsprechenden Handler an das BackgroundWorker.ProgressChanged Ereignis BackgroundWorker.ProgressChanged . Wenn Sie möchten, dass etwas auf der GUI passiert, sobald der BackgroundWorker fertig ist , dann hängen Sie einfach Ihren Handler an, um die GUI für das BackgroundWorker.RunWorkerCompleted Ereignis zu aktualisieren.

Wo genau legen Sie die Eigenschaft Enabled ? Wenn Sie dies in der DoWork Ereignisbehandlungsroutine tun, wird dieser Code in einem anderen Thread ausgeführt als die Schaltfläche, für die die Ausnahme erstellt wurde. Um dies zu BeginInvoke , sollten Sie BeginInvoke . Der Einfachheit halber könnte es in eine Methode wie folgt eingepackt werden:

 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 

Jetzt können Sie diese Methode sicher aufrufen, um jedes Steuerelement aus einem beliebigen Thread zu aktivieren oder zu deaktivieren:

 SetControlEnabled(someButton, False) 

Form1_Load den folgenden Code in der Form1_Load (oder was auch immer Ihr Formular ist) Sub:

 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False 

Es behebt alle Probleme mit blockierten Cross-Thread-Operationen.

Der bessere Weg dazu in VB.NET ist die Verwendung einer Extension , die sehr gut aussehenden Code zum Cross-Threading von GUI Control Calls macht.

Fügen Sie diese Codezeile zu jedem Modul hinzu, das Sie haben.

  _ 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 

Jetzt können Sie einen Cross-Thread-Steuercode schreiben, der nur 1 Zeile lang ist, für jeden Steueraufruf.

Nehmen wir an, Sie möchten eine ComboBox löschen und sie wird aus Threads oder ohne Threads aufgerufen, die Sie jetzt einfach verwenden können

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

Möchten Sie etwas hinzufügen, nachdem Sie es gelöscht haben?

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

Sie können die Eigenschaft eines Steuerelements, die sich im Benutzeroberflächenthread befindet, nicht direkt von einem anderen Thread aus festlegen. Es kann getan werden, hier ist ein Beispiel von 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 

Ihr Form_Load () schreibt bitte unter den Code-Teil. Alle deine Probleme werden getriggers.

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

Schlagen Sie vor, AutomationPeer zu verwenden.

Zum Beispiel unter Code-Calls Execute Button, wenn ich die F5-Taste drücke. Wenn Sie möchten, dass ein Thread oder ein Hintergrund-Worker ein Ereignis oder eine function aufruft, können Sie Automation Peer verwenden. In Ihrem Fall anstelle der Schaltfläche (die ich hier verwendet habe) können Sie das Textfeld mit der entsprechenden Eigenschaft aufrufen.

 '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 

Grüße RV

 CheckForIllegalCrossThreadCalls = False