2009-08-25 7 views
2

Ich sah mich auf der Website und die Fragen zu diesem Thema waren für C# (die Anwendung, die ich pflege geschrieben ist in VB.NET geschrieben), so entschuldige ich mich, wenn ich übersehen ein.Cross-Thread-Operation nicht gültig VB.NET

Hier ist, wo ich mein Thread nenne:

Private Sub saveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles saveBtn.Click 
    If Not LoadedFilePath = String.Empty Then 
     Dim oTrd = New Threading.Thread(AddressOf SaveData) 
     oTrd.Start() 
    End If 
End Sub 

Und hier sind die Methoden:

Private Sub SaveData() 
    SaveData(LoadedFilePath) 
End Sub 
Private Sub SaveData(ByVal filepath As String) 
    If InvokeRequired Then 
     Me.Invoke(New MethodInvoker(AddressOf SaveData)) 
    End If 
    Try 
     Me.Cursor = Cursors.WaitCursor 
     Dim oSettings As New SettingsClass(filepath) 
     Dim oEnc As New AES 
     With oSettings 
      //' Code removed for brevity 
     End With 
     oEnc = Nothing 
     oSettings.SaveSettings() 
     savedLbl.Visible = True 
     If SavedTimeout IsNot Nothing Then 
      Try 
       SavedTimeout.StopEvent() 
      Catch 
      End Try 
     End If 
     SavedTimeout = New TimedEvent(Now.AddSeconds(5)) 
     SavedTimeout.StartEvent() 
     Me.Cursor = Cursors.Default 
    Catch ex As Exception 
     MsgBox(ex.Message) 
    End Try 
End Sub 

Die Save-Funktion funktioniert gut, aber ich habe den Cross-Thread-Fehler bei der Programm versucht den Cursor zurück auf Standard zu setzen. Was kann ich tun, um dieses Problem zu beheben?

Antwort

5

Ihre Methode zum Aufrufen der Methode im Thread des Eigentümers (GUI) ist falsch. Wenn ein Aufruf erforderlich ist, sollten Sie den Rest des Codes in der Methode nicht ausführen. Wenn Sie dies tun, werden Sie es sowohl im GUI-Thread als auch im Hintergrund-Thread ausführen, und wenn Sie versuchen, über den Hintergrundthread auf die GUI-Elemente zuzugreifen, erhalten Sie den Cross-Thread-Fehler.

sollte der Aufruf wie folgt aussehen:

Private Sub SaveData(ByVal filepath As String) 
    If InvokeRequired Then 
     Me.Invoke(New MethodInvoker(AddressOf SaveData)) 
    Else 
     ... the actual code 
    End If 
End Sub 

Aber warum starten Sie die Methode in einem Hintergrund-Thread, wenn es sich in der GUI-Thread sowieso aufzurufen hat?

+0

wow haha ​​ich kann nicht glauben, dass ich das andere vergessen habe ... Ende des Tages FTL! Danke für die Lösung :) – Anders

+0

@Anders: Persönlich würde ich es ohne die 'Else' verlassen und fügen Sie einfach eine 'Return' direkt nach' Me.Invoke() ', um die Methode von weiteren Ausführen zu stoppen. Es hilft, den Code durch Reduzierung der Verschachtelung einfach zu lesen. – STW

+0

@yoooder: Danke für den Tipp, das werde ich mir merken. – Anders

1

Sie haben einen Hilfsthread gestartet, der nicht auf der Benutzeroberfläche aufgerufen werden darf. Sie dürfen den Cursor nur vom UI-Thread selbst setzen.

Um dies zu erreichen, haben Sie ein Ereignis von Ihrem Helfer-Thread zu feuern, die den UI-Thread, dass Ihre Arbeit und beendet erzählen, dass er die Cursor zurück oder alternativ tut dies über Aufrufe in den UI-Thread festlegen:

0

In einer Windows Forms-Anwendung mit mehreren Threads ist es nicht zulässig, eine Methode oder Eigenschaft für ein Steuerelement von einem anderen Thread als demjenigen aufzurufen, der sie erstellt hat. Alle Thread-übergreifenden Aufrufe müssen mithilfe der Control.Invoke-Methode oder der Control.BeginInvoke-Methode explizit an den Thread gemahnt werden, der das Steuerelement erstellt hat (normalerweise der Hauptthread).

Hier ist eine Webseite, die Sie, um Ihnen bei der Lösung dieses Problems verwenden können:

http://www.dreamincode.net/forums/showtopic35616.htm C#

http://www.codeproject.com/KB/vb/ISinchronizedInvoke.aspx VB.NET