Backgroundworker in einer Klasse vewenden

  • VB.NET

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

    Backgroundworker in einer Klasse vewenden

    Hi,

    ich habe ein großes Problem. Ich bekomme es nicht hin, einen Backgroundworker in einer Klasse zum Laufen zu bekommen.
    Mein Ziel ist es, eine Endlosschleife, welche momentan in einem seperaten Thread läuft, in den Backgroundworker/Timer zu packen, damit die CPU nicht so ausgelastet wird.

    Leider weiß ich nicht, wie ich dem neu erstelleten Backgroundworker/Timer nun auch die Methode beibringen kann, welche er abarbeiten soll ... ?

    VB.NET-Quellcode

    1. Dim bgwService As New BackgroundWorker
    2. Public Sub new()
    3. bgwService.RunWorkerAsync()
    4. End Sub
    5. Private Sub meineMethode() 'Wie kann ich dem BGW sagen, dass er diese Methode ausführen soll?
    6. 'Die Schleife.
    7. End Sub


    Falls ich das nicht irgendwie auf die Reihe bekomme, sieht's schwarz aus für mein Projekt. Da arbeite ich gerade in 5 Thread mit Endlosschleifen, die CPU wird absolut unverhältnismäßig ausgelastet.
    Ich hoffe, ihr könnt mir helfen.

    MrWebber

    PS: Ich habe es mit dem Event versucht, aber da erhielt ich eine Fehlermeldung:

    VB.NET-Quellcode

    1. Private Sub meineMethode() Handles bgwService.DoWork
    2. 'Die Schleife.
    3. End Sub


    Die Handles-Klausel erfordert eine WithEvents-Variable, die im enthaltenden Typ oder einem seiner Basistypen definiert wird.


    Ich verstehe sie nicht.

    Variablen über das Internet senden? [VB.NET] Universal Ticket.dll :thumbup:
    Lasse deine Programme selbstständig lernen! [VB.NET] Brain.dll
    :thumbsup:

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „mrwebber“ ()

    Ein BackgroundWorker ist auch nur ein Thread, welcher bereits mit einigen Service-Merkmalen ausgestattet ist.
    Wenn Dein separater Thread zu Deiner Zufriedenheit läuft, lass es so.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo Rod, ich habe oben noch ein Stück ergänzt. Das Problem ist die CPU-Auslastung ;)

    EDIT: Was ich gemerkt habe, ist, dass ein Timer/BGW einfach fast keine CPU-Auslaustung verursacht, obwohl ein Timer sozusagen ja auch eine Endlosschleife ist (bei mir ausreichen würde). Daher würde ich gerne umstellen.

    Variablen über das Internet senden? [VB.NET] Universal Ticket.dll :thumbup:
    Lasse deine Programme selbstständig lernen! [VB.NET] Brain.dll
    :thumbsup:
    "in den Timer packen"
    und
    "damit die CPU nicht so ausgelastet wird"
    ergibt nicht viel Sinn.
    Ein Timer ist genau das umgekehrte wie ein BGW.
    Und die CPU wird gleich belastet. Unabhängig davon, wo der Code abgearbeitet wird.

    Hier ein Tutorial zum BGW: [VB.NET] Multithreading mit BackgroundWorker

    Eine Form ist auch nur eine Klasse. Wenn Du schon einen BGW zum Laufen gebracht hast, ist es in der Klasse nur das selbe.


    Edit:

    Nochmal: Die CPU wird beidesmal gleich belastet. Und das ist ganz ehrlich gesagt auch Wurscht. Worum es geht ist, die komplizierte Operation in einen anderen Thread auszulagern (->BGW), damit der GUI-Thread weiterlaufen kann und das Programm nicht "einfriert".

    Der BGW muss in der Klasse so deklariert sein:

    VB.NET-Quellcode

    1. [Scope] WithEvents BGWName As New System.ComponentModel.BackGroundWorker


    Das WithEvents am Anfang gibt an, dass er von der Handles-Direktive erkannt wird.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Hallo Niko. Ich habe schon sehr oft BGWs in Forms benutzt. Da hat aber auch das Event funktioniert. Hier (in meiner Klasse) geht das Event nicht. Ich verstehe die Meldung nicht (Siehe erster Post)

    EDIT: Danke Niko. Mit diesem WithEvents funktioniert es. Aber was bedeutet dieses Withevents? Was ist eine Handles-Direktive? :)
    EDIT: PS: Mit dem Timer wird das wohl genauso funktionieren, hoffe ich :D das kann ich jetzt leider nicht mehr testen, weil ich weg muss ... :whistling:

    Variablen über das Internet senden? [VB.NET] Universal Ticket.dll :thumbup:
    Lasse deine Programme selbstständig lernen! [VB.NET] Brain.dll
    :thumbsup:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „mrwebber“ ()

    WithEvents sagt aus, dass das Objekt Events wirft, welche beobachtet werden.

    Manche Methoden-Deklarationen enden mit einem "Handles Bla.OnBlub", diese werden dadurch erkannt und Eventhandler geaddet.

    WithEvents hat jedoch den Nachteil, dass diese EventWatcher nicht mehr entfernt werden, daher sollte man das Manuell machen

    VB.NET-Quellcode

    1. ' In einer Lade-Routine
    2. AddHandler Object.Event, AddressOf MeineSubMitEventHandlerSignatur
    3. ' In einer Unload-Routine
    4. RemoveHandler Object.Event, AddressOf MeineSubMitEventHandlerSignatur
    5. ' Weiter im Code
    6. Private Sub MeineSubMitEventHandlerSignatur(sender As Object, e As EventArgs)
    7. ' Bla
    8. End Sub


    Nicht entfernte Handler beobachten Events (welche gegebenenfalls garnicht mehr existieren) eben weiter, was Leistung kostet (erst in der Masse bemerkbar). Daher benutze ich immer, wenn ich EventHandler habe welche das Programm nicht bis zum Schluss überdauern (und meistens selbst dann um es einheitlich zu halten), eben dieses AddHandler und RemoveHandler
    WithEvents sagt dem Compiler, dass es für die Handles-Direktive verwendet werden kann. Das ist soziemlich alles, was es bedeutet.
    Wichtiger ist die Handles-Direktive selbst.

    VB.NET-Quellcode

    1. Private WithEvents BGW As BackGroundWorker
    2. v v Das ist die Handles-Direktive (k.a. warum das "Direktive" heißt)
    3. Private Sub BGW_DoWork(...) Handles BGW.DoWork
    4. End Sub

    Die Sache mit dem Handles ist so:

    Das obrige Beispiel ergibt in wirklichkeit das hier:

    VB.NET-Quellcode

    1. <AccessedThroughProperty("BGW")> _
    2. Private _BGW As BackGroundWorker
    3. Private Overridable Property BGW As BackGroundWorker
    4. Get
    5. Return _BGW
    6. End Get
    7. Set (value As BackGroundWorker)
    8. Dim Handler As New DoWorkEventHandler(BGW_DoWork)
    9. If _BGW IsNot Nothing Then
    10. RemoveHandler _BGW.DoWork, Handler
    11. End If
    12. _BGW = value
    13. If _BGW IsNot Nothing THen
    14. AddHandler _BGW.DoWork, Handler
    15. End If
    16. End Set
    17. End Property
    18. Private Sub BGW_DoWork(...)
    19. End Sub


    Wie man sieht, wird eine Variable _BGW angelegt und eine Property BGW. Immer, wenn Du im Code (in Deinem Code) auf BGW zugreifst, greifst Du in Wirklichkeit auf die Property zu.
    Wenn Du jetzt den alten BGW überschreibst (also der Set-Teil der Property aufgerufen wird), wird zuerst der alte EventHandler vom alten BGW entfernt, dann wird der neue BGW abgelegt und dann wird ein neuer EventHandler hinzugefügt.
    Das erleichtert die Sache beim Schreiben sehr.

    Das Handles gibt's in C# zum Beispiel nicht.
    Deshalb würde es da so aussehen (übersetzt):

    VB.NET-Quellcode

    1. Private BGW As BackGroundWorker
    2. Public Sub New()
    3. 'Hier wird noch InitializeComponent aufgerufen
    4. BGW = New BackGroundWorker
    5. AddHandler BGW.DoWork, AddressOf BGW_DoWork
    6. 'Oder:
    7. AddHandler BGW.DoWork, New DoWorkEventHandler(BGW_DoWork)
    8. End Sub
    9. Private Sub BGW_DoWork(...)
    10. End Sub


    Man muss sich selbst um den EventHandler kümmern.

    Wenn man jetzt aber irgendwo der Variable BGW eine neue Instanz eines BackGroundWorkers zuweist, dann bleibt der alte im Arbeitsspeicher und arbeitet munter weiter mit seinen Events (Da würde ein Timer besser als Beispiel passen. Der Timer würde weiterhin Den EventHandler aufrufen.)

    Das Handles-Schlüsselwort nimmt uns da ein Bisschen Arbeit ab.


    Edit: @Kagurame: Nicht ganz. Man muss einfach die Variable auf Nothing setzen. Intern wird dann der EventHandler auch entfernt.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    mrwebber schrieb:

    Das Problem ist die CPU-Auslastung ;)
    Es macht wohl einen Unterschied, ob Du eine Methode in der Timer-Tick-Prozedur einer Form oder in einem separaten Thread abarbeitest.
    Ob dieser Thread ein schnöder Threadding.Thread oder ein BackgroundWorker ist, ist egal.
    Ein BackgroundWorker macht sich leichter beim Bearbeiten vom Abarbeitungsstatus.
    Wenn Du den BGW im Designer auf die Form ziehst, ist doch bereits alles vorgefertigt.
    Form mit Button, BackgroundWorker, ProgressBar

    VB.NET-Quellcode

    1. BackgroundWorker1.WorkerReportsProgress = True

    Spoiler anzeigen

    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_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    6. ProgressBar1.Value = e.ProgressPercentage
    7. End Sub
    8. Private Sub BackgroundWorker1_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    9. MessageBox.Show("Feddich")
    10. End Sub
    11. Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    12. 'BackgroundWorker1SeineArbeit
    13. For i = 0 To 100
    14. System.Threading.Thread.Sleep(10)
    15. BackgroundWorker1.ReportProgress(i)
    16. Next
    17. End Sub
    18. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    mrwebber schrieb:

    EDIT: Danke Niko. Mit diesem WithEvents funktioniert es. Aber was bedeutet dieses Withevents? Was ist eine Handles-Direktive?
    Jo, da fehlen Grundlagen. Deshalb verstehst du die Fehlermeldung nicht, und folglich geht garnix weiter.

    ich empfehle, das Entwicklerbuch von Löffelmann zu lesen, die 2005er Version behandelt diese Grundlagen am besten - kann man kostenlos downloaden den Schinken.

    Wo du auf die Schnelle derlei Schlüsselworte nachschlagen kannst: VB-Sprachreferenz auf MSDN

    Aber das hilft dir nur punktuell, und kann ein systematisches Erlernen der Sprache und Entwicklungswerkzeuge nicht ersetzen.

    Aber ich bin froh, dass du deine Frage so präzise formulierst - viele, glaub sogar die Mehrheit ist ausserstande, anzugeben, was im Einzelnen nicht verstanden wird.