Fehler bei einfachem Code mit BackgroundWorker: System.InvalidOperationException

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von SpaceyX.

    Fehler bei einfachem Code mit BackgroundWorker: System.InvalidOperationException

    Hallo,

    ich habe ein kleines problem. Wenn ich versuche mit einem backgroundworker auf eine progressbar zuzugreifen wird eine fehlermeldung ausgestoßen. Dieser Fehler tritt aber nur im Debugger auf, nicht wenn man das programm zb auf dem desktop ausführt. Woran liegt das und wie kann ich das problem beheben?
    Der fehler tritt genau beim drücken auf den Button auf.

    Hier der fehlercode:
    "
    System.InvalidOperationException wurde nicht von Benutzercode behandelt.

    Message=Ungültiger threadübergreifender Vorgang: Der Zugriff auf das
    Steuerelement ProgressBar1 erfolgte von einem anderen Thread als dem
    Thread, für den es erstellt wurde.
    "

    und hier ein beispielprogramm extra für euch ;)


    Edit by Manschula: Programm-Downloads sind außerhalb des Showrooms nicht gestattet --> Dateianhang entfernt

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Manschula“ ()

    Wieso hängst du da ne .exe ran? Soll ich die downloaden? Ist das ein Virus? Was bringt mir die? Pack die sofort wieder weg!
    Damit wir dir helfen können musst du den code posten und nicht die .exe hochladen...

    Der Backgroundworker lagert die Arbeit in einem eigenen Thread aus. Offensichtlich hast du in diesem Thread auf ein control des GUI-Hauptthreads zugegriffen.
    Auf die Controls darf aber nur der Hauptthread zugreifen.
    Du kannst es dennoch machen, wenn du mit invoke arbeitest.
    Wenn Du etwas sinnvolles machen willst, dann lad die Projektdatei hoch. Eine .exe wird weder jemand starten, noch hilft sie in irgendeiner Weise, Dein Problem zu sehen. Ist nicht bös gemeint, wirklich nicht.

    Zum Problem: Ich hab folgendes Beispiel.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    3. Me.BackgroundWorker1.WorkerReportsProgress = True
    4. Me.BackgroundWorker1.RunWorkerAsync()
    5. End Sub
    6. Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    7. For i As Integer = 1 To 100
    8. Me.BackgroundWorker1.ReportProgress(i, "test")
    9. Threading.Thread.Sleep(1000)
    10. Next
    11. End Sub
    12. Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    13. Me.ProgressBar1.Value = e.ProgressPercentage
    14. Me.Text = DirectCast(e.UserState, String)
    15. End Sub
    16. End Class


    Ich arbeite nie mit BackgroundWorkern, ich nutze Threads. Von Threads weiss ich, dass sie nur über Delegates auf Controls des GUI-Threads zugreifen können. Ein BGW ist auch nichts anderes als ein extra Thread. Du hast bei nem BGW nur sauberen Zugriff auf die Controls, wenn Du sie im ProgressChanged-Event ansprichst. So denk ich mir das. Kann natürlich auch anders sein, aber ist logisch. Du musst, bevor Du ein ReportProgress absetzt, den BGW auf WorkerReportsProgress = True setzen. Steht alles im Code. Das sollte Dir helfen.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    haha stimmt hab den code vergessen :D

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    3. BackgroundWorker1.RunWorkerAsync()
    4. End Sub
    5. Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    6. ProgressBar1.Value += 5
    7. End Sub
    8. End Class


    ganz einfach und simpel um das problem zu verstehen. und markus.obi kannst du mir für invoke ein beispiel geben wie man das anwendet? 8o
    Hast Du Dir meine Antwort überhaupt angesehen? Da steht nämlich, wie es geht. Bei nem BGW brauchst nicht zwingend Delegates.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Mithilfe eines Delegaten geht das so:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    3. Me.BackgroundWorker1.RunWorkerAsync()
    4. End Sub
    5. Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    6. For i = 1 To 100
    7. Me.Invoke(New ProgressbarDelegate(AddressOf UpdateProgressBar), {i})
    8. Threading.Thread.Sleep(50)
    9. Next
    10. End Sub
    11. Delegate Sub ProgressbarDelegate(ByVal v As Int32)
    12. Private Sub UpdateProgressBar(ByVal value As Int32)
    13. ProgressBar1.Value = value
    14. End Sub
    15. End Class


    Wobei ich zugeben muss, dass diese Lösung bei einem einfachen BGW nicht nötig ist, da meistens ReportProgress ausreicht.
    Der Ausdruck {i} ist ein Array, in das du die Übergabeparameter reinschreibst. In diesem Fall: 1 Argument vom Typ Int32.
    Der Delegate ProgressbarDelegate kann übrigens auch an anderer Stelle verwendet werden, solange die Parameter vom gleichen Typ sind.
    Geht auch als Einzeiler:

    VB.NET-Quellcode

    1. Me.Invoke(Sub(i As Integer) Me.ProgressBar1.Value = i, New Object() {50})
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o