Programm schneller machen durch Backgroundworker anstatt mehreren Timern ?

  • VB.NET

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von OneWorld.

    Programm schneller machen durch Backgroundworker anstatt mehreren Timern ?

    Hallo Forum


    Ich bin zuzeit ein Programm am schreiben, welches mit vielen Timern arbeitet. Wie man aus der Überschrift schon erraten kann wird je mehr Timer ich verwende die Anwendung langsamer. Nun zu meiner Frage: da ich mich nicht so recht mit Backgroundworkern auskenne, wollte ich fragen, ob es möglich wäre 4 Timer mit einem BackgroundWorker zu ersetzen. Bei dem 5. Timer merkt man schon, dass die anderen Timer nicht mehr so ganz wie vorher arbeiten.


    Bitte um Ratschläge

    Gruß OneWorld
    Youtube Info Library 2013 jetzt im Showroom.
    Danke für die schnelle Hilfe. :D Ich verwende die Timer um CPU und RAM Auslastung abzufragen geht auch super nur wenn ich noch einen Timer starte fangen die anderen an langsamer zu werden. Das ist mein Problem.
    Und die Frage ist geht das auch einfacher ?
    Youtube Info Library 2013 jetzt im Showroom.
    Timer1 ist für die performance Counter
    Timer2 Fragt die Auslastung ab
    Timer3 ist für eine Combobox die mir Die Festplattendaten liefert

    [Edit] Nach diesem Tutorial gemacht ( [VB.NET] CPU-, RAM- Auslastung, CPU-Temperatur und freien Speicher der jeweiligen Festplatte anzeigen lassen )
    Youtube Info Library 2013 jetzt im Showroom.
    Wenn die Einzelnen "Auslese-Vorgänge" (=> performanceCounter, Auslastungs-Abfrage & Auslesen der Festplattendaten) länger dauern, dann würde ich diese in einen BGW auslagern. Ein (!) Timer soll dann regelmäßig sagen, dass jetzt Daten aktualisiert werden sollen - sprich der/die BGW (einer sollte dafür aber auch reichen) beginnen ihre Arbeit. Ist der BGW fertig, dann feuert er das Complete-Event - ein Zeichen für dich, die GUI (also labels, die Combobox, etc) mit den neuen Daten zu füttern.

    Edit: "Merkst" du, dass die Timer ausbremsen oder vermutest du das nur? Nenn auch mal das eingestellte Interval^^
    Aber das kannst Du doch alles mit einem Timer steuern. Überdenk mal ein bisschen die Architektur Deines Programmes. Mit den Timern killst Du Dein Programm, das hast Du ja schon selber erkannt. Mach Dir doch für die einzelnen Abfragen extra Klassen. Statte jede Klasse mit einer Methode z. B. "GetValues()" oder so ähnlich aus und ruf im Hauptprogramm, beim Timer.Tick die Methoden auf. Probiers mal, es geht alles mit einem Timer, wenn es denn schon ein Timer sein muss.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Mal ernsthaft?
    Timer um ne Combobox zu befüllen?

    Dir ist schon klar, dass wenn nen halbwegs großes Projekten deinen Programmierstil verwenden würde, es wahrscheinlich 500-5000 Timer am laufen hätte?


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Am besten ich überdenke das alles noch einmal und dann melde ich mich wieder falls Probleme entstehen @thefiloe stimmt irgendwo war nicht gerade schlau von mir :D
    Youtube Info Library 2013 jetzt im Showroom.
    Falls Du Dich dazu entscheidest, die Abfragen in eigene Klassen auszulagern, so wie ich es Dir vorgeschlagen habe, ist hier ein guter Zeitpunkt, um sich mit Interfaces zu befassen. Nur so als kleiner Tip.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    wieso Interfaces?

    eine gemeinsame Basisklasse für die verschiedenen Abfrage-Klassen scheint mir einfacher.
    möglicherweise noch einfacher mag sein, einem Delegaten verschiedenartige Abfrage-Methoden zuzuweisen.

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

    Aja, das ist ein seeeehr altes Tutorial von mir,
    wie schon öfters gesagt, das kannst du alles auf einen Timer unschreiben.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Hallo :)

    also, meiner Ansicht nach bieten sich Interfaces für dieses Problem an. Ich bin damals selbst an dem Problem mit den Timern gescheitert, als ich mir selbst eine kleine "Sidebar" erstellen wollte. Irgendwann kam dann der Moment, wo ich mich mehr mit Klassen und Interfaces beschäftigt habe. Eines Vorweg, ich behaupte nicht, dass ich alles zu 100% kapiere, aber ich glaube, dass der TE genau hier ein Stückchen weiter kommt. Also, ich hab Dir wie versprochen ein kleines Beispiel erstellt. Es gibt 3 Klassen: Eine Klasse liest den freien Festplattenspeicher aus, eine den freien Arbeitsspeicher, eine gibt einfach nur die Zeit aus. Das soll Dir verdeutlichen, wie man alles mit einem Timer unter die Haube bekommt. Es gibt sicher andere Möglichkeiten, aber das ist mein Vorschlag. Erst mal die 3 Klassen, die die Werte auslesen.

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class HDDSpaceReader : Implements IReaderUpdate
    3. Private _driveLetter As String
    4. Public Property driveLetter As String
    5. Get
    6. Return _driveLetter
    7. End Get
    8. Set(value As String)
    9. _driveLetter = value
    10. End Set
    11. End Property
    12. Public Event UpdateDone(ByVal driveLetter As String, ByVal freeSpace As Long)
    13. Public Sub New(ByVal driveLetter As String)
    14. Me.driveLetter = driveLetter
    15. End Sub
    16. Public Sub Update() Implements IReaderUpdate.Update
    17. Dim dI As New DriveInfo(Me.driveLetter)
    18. Dim freeSpace As Long = dI.AvailableFreeSpace
    19. RaiseEvent UpdateDone(Me.driveLetter, freeSpace)
    20. End Sub
    21. End Class


    VB.NET-Quellcode

    1. Public Class MemoryReader : Implements IReaderUpdate
    2. Public Event UpdateDone(ByVal freeMemory As ULong)
    3. Public Sub New()
    4. End Sub
    5. Public Sub Update() Implements IReaderUpdate.Update
    6. Dim freeMem As ULong = My.Computer.Info.AvailablePhysicalMemory
    7. RaiseEvent UpdateDone(freeMem)
    8. End Sub
    9. End Class


    VB.NET-Quellcode

    1. Public Class TimeReader : Implements IReaderUpdate
    2. Public Event UpdateDone(ByVal timeString As String)
    3. Public Sub New()
    4. End Sub
    5. Public Sub Update() Implements IReaderUpdate.Update
    6. Dim timeString As String = Now.ToLongTimeString()
    7. RaiseEvent UpdateDone(timeString)
    8. End Sub
    9. End Class


    Wie Du in den Klassendefinitionen sehen kannst, implementieren alle 3 Klassen die Schnittstelle (Interface) "IReaderUpdate".

    VB.NET-Quellcode

    1. Public Interface IReaderUpdate
    2. Sub Update()
    3. End Interface


    Eine Schnittstelle ist grundsätzlich nichts anderes, als die Vorgabe, was eine Klasse können muss. Und wie Du in den Klassen siehst haben alle 3 die Methode:

    VB.NET-Quellcode

    1. Public Sub Update() Implements IReaderUpdate.Update
    2. End Sub


    Damit hast Du die Möglichkeit, jede dieser 3 Klassen über eine "Schnittstellenvariable" aufzurufen. Das gibt Dir im Hauptprogramm den Vorteil, dass Du alle 3 Klassen in einer

    VB.NET-Quellcode

    1. Private _listReaders As New List(Of IReaderUpdate)


    zusammenfassen kannst. Der Code fürs Hauptprogramm sieht so aus.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private WithEvents _t As New Timer()
    3. Private _listReaders As New List(Of IReaderUpdate)
    4. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    5. Dim hR As New HDDSpaceReader("c:")
    6. Dim mR As New MemoryReader()
    7. Dim tR As New TimeReader()
    8. AddHandler hR.UpdateDone, AddressOf HDDSpaceReader_UpdateDone
    9. AddHandler mR.UpdateDone, AddressOf MemoryReader_UpdateDone
    10. AddHandler tR.UpdateDone, AddressOf TimeReader_UpdateDone
    11. _listReaders.Add(hR)
    12. _listReaders.Add(mR)
    13. _listReaders.Add(tR)
    14. UpdateReaders()
    15. _t.Interval = 1000
    16. _t.Start()
    17. End Sub
    18. Private Sub HDDSpaceReader_UpdateDone(ByVal driveLetter As String, ByVal freeSpace As Long)
    19. Me.Label1.Text = freeSpace.ToString("N0") & " Bytes free. Drive: " & driveLetter.ToUpper()
    20. End Sub
    21. Private Sub MemoryReader_UpdateDone(ByVal freeMemory As ULong)
    22. Me.Label2.Text = freeMemory.ToString("N0") & " Bytes free"
    23. End Sub
    24. Private Sub TimeReader_UpdateDone(ByVal timeString As String)
    25. Me.Label3.Text = timeString & " Uhr"
    26. End Sub
    27. Private Sub _t_Tick(sender As Object, e As System.EventArgs) Handles _t.Tick
    28. UpdateReaders()
    29. End Sub
    30. Private Sub UpdateReaders()
    31. For Each iReader In _listReaders
    32. iReader.Update()
    33. Next
    34. End Sub
    35. End Class


    Wie der ErfinderDesRades sagte, gibts hier auch die Möglichkeit, eine Basisklasse für alle "Reader" zu erstellen und die entsprechenden Reader von dieser Klasse erben zu lassen. Aber, da man hier nur eine Methode aufrufen muss, finde ich Interfaces eleganter. Es ist beides möglich und eine gemeinsame Basisklasse hat halt wieder andere Vorteile. Nur ich finde Interfaces einfacher zu verstehen.

    Die Schnittstellenvariable ermöglicht es Dir, auf die in der Schnittstelle definierte Sub, zuzugreifen. Im Timer.Tick-Event rufst Du genau diese Sub dann auf.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    also ich habe die Messwerte jetzt als Datensatz aufgefasst, dem ich auch eine Update-Methode spendiere, in der er alle seine Werte updatet.

    Nix mit Interface oder Basisklasse oder Delegaten - einfach einfacher Code:

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class frmReadHardware
    3. Private _Hardware As New HardWareProperties("c:")
    4. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    5. With _Hardware
    6. .Update()
    7. Label1.Text = String.Concat(.DriveSpace, " Bytes free on """, .Drive.Name, """")
    8. Label2.Text = String.Concat(.Memory, " Bytes free on Memory")
    9. Label3.Text = .TimeStamp.ToString("G")
    10. End With
    11. End Sub
    12. End Class
    13. Public Class HardWareProperties
    14. Public ReadOnly Drive As DriveInfo
    15. Public DriveSpace As Long, Memory As ULong, TimeStamp As Date
    16. Public Sub New(ByVal driveLetter As String)
    17. Drive = New DriveInfo(driveLetter)
    18. End Sub
    19. Public Sub Update()
    20. DriveSpace = Drive.AvailableFreeSpace
    21. Memory = My.Computer.Info.AvailablePhysicalMemory
    22. TimeStamp = Date.Now
    23. End Sub
    24. End Class
    wobei die DriveSpace- und die TimeStamp- Properties auch noch sinnlos sind, weil von einem DriveInfo kann man jederzeit den AvailableSpace abfragen (dito mitte Uhrzeit).

    Aber vlt. kommen ja noch zig weitere zu ermittelnde Werte hinzu

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

    Ja, ist auch ne schöne Lösung, aber diese Klasse wird einfach nur eklig unübersichtlich, wenn noch weitere Komponenten hinzukommen. Schön alleine deswegen sollte man die einzelnen Komponenten in eigene Klassen aufteilen. Meine Meinung. Schon alleine der Konstruktor wird einfach nur übel, wenn noch Performance-Counter hinzukommen....
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Imo sollte man da nix aufteilen, solange das Ermitteln eines Wertes mit ein oder 2 Zeilen getan ist.
    Unter der Klassenbezeichnung "HardwareProperties" ist das eine Einheit, die man zunächstmal nicht auseinanderpflücken sollte.
    Ich finde Klassen bis 200 Zeilen Code absolut gut lesbar - besser, als wenn man da zw. mehreren Dateien rumswitchen muß, um ein Gesamtbild zu erhalten.

    Wohingegen ich mit meinem Datensatz-Ansatz noch VerkleinerungsPotential im Form-Code habe, wennich Databinding implementiere :D

    Grade das mit den vielen EventHandlern bläst den Form-Codebehind enorm auf.
    Grade Form-Codebehind wird ja bei anspruchsvollen Oberflächen sehr schnell unübersichtlich, und geht oft weit über 200 Zeilen hinaus.
    Nicht nur unübersichtlich wegen der vielen Zeilen, sondern v.a. auch wegen der verschiedenen "Themen", die da beackert werden - da laufen ja Laden und Speichern, Optionen, TextChanges, alle möglichen Button-Clicks und alles zusammen, was inhaltlich eiglich nix mitnander zu tun hat.

    im Anhang beide Lsg im Vergleich
    Dateien

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Ja, geb ich Dir auch recht. Mit der Zeit entwickelt eben jeder seinen eigenen Programmierstil. Es geht auch nicht darum, dem TE seinen Stil aufzuzwingen. Mir gings halt damals so, als ich so etwas entwickeln wollte, waren Interfaces ein Fremdwort. Als ich mich damit befasste, hab ich viel dazu gelernt. Diesen "Sprung" wollte ich dem TE aufzeigen. Welches Beispiel er für sich als gut erachtet ist seine Sache. Immer führen viele Wege nach Rom und es ist gut, dass er unterschiedliche Herangehensweisen zu sehen bekommt.

    Du hast bestimmt viel mehr Erfahrung wie ich und weisst auch mehr und vielleicht seh ich den Zusammenhang jetzt auch nicht. Darum ist ein Forum da. Das jeder seine Sicht kundtut und der TE sich dann seine Lösung für sich selbst erarbeitet.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o