Thread verursacht wachsenden Speichergebraucht

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Thread verursacht wachsenden Speichergebraucht

    Moin,

    ich habe mir einen Simplen Thread gebastelt, der ein Gridview löschen, refreshen oder resizen soll. Der läuft in einer Dauerschleife und verursacht bei mir anscheinend ein erhöhten Speicherbedarf bis die Anwendung aussteigt.

    Ich bin noch ein wenig Greenhorn wenn es um Threading geht, daher meine frage, was mache ich falsch?


    Das ist mein Thread:

    VB.NET-Quellcode

    1. Private Delegate Sub ResizeColumnsDelegate()
    2. Private Delegate Sub ClearAlarmboxDelegate()
    3. Private Delegate Sub AlarmboxRefreshDelegate()
    4. Private Delegate Sub WriteAlarmboxDelegate(Datetime As String, Group As String, Text As String)
    5. Private Sub Alarmdatenlesen()
    6. Dim DeliResize As New ResizeColumnsDelegate(AddressOf ResizeColumns)
    7. Dim DeliWrite As New WriteAlarmboxDelegate(AddressOf WriteAlarmbox)
    8. Dim DeliClear As New ClearAlarmboxDelegate(AddressOf ClearAlarmbox)
    9. Dim DeliRefresch As New AlarmboxRefreshDelegate(AddressOf AlarmboxRefresh)
    10. SyncLock Me
    11. While True
    12. If (Me.InvokeRequired) Then
    13. Me.Invoke(DeliResize)
    14. Else
    15. Me.ResizeColumns()
    16. End If
    17. If Not Main._SendRecieve.Connectionstate Then
    18. If (Me.InvokeRequired) Then
    19. Me.Invoke(DeliResize)
    20. Me.Invoke(DeliClear)
    21. Me.Invoke(DeliWrite, Date.Now.ToString, "PLC", "No Connetion")
    22. Else
    23. Me.ResizeColumns()
    24. Me.ClearAlarmbox()
    25. Me.WriteAlarmbox(Date.Now.ToString, "PLC", "No Connetion")
    26. End If
    27. End If
    28. If (Me.InvokeRequired) Then
    29. Me.Invoke(DeliRefresch)
    30. Else
    31. Me.AlarmboxRefresh()
    32. End If
    33. Thread.Sleep(500)
    34. End While
    35. End SyncLock
    36. End Sub


    Und so starte ich den Thread:

    VB.NET-Quellcode

    1. Private AlarmThread As New Thread(New ThreadStart(Sub() Alarmdatenlesen()))
    2. Sub New() 'ByRef Alarmtable As Alarmboxdatatable)
    3. 'Nicht zur Designzeit ausfuehren:
    4. If System.ComponentModel.LicenseManager.UsageMode = System.ComponentModel.LicenseUsageMode.Designtime Then Return
    5. ' Dieser Aufruf ist für den Designer erforderlich.
    6. InitializeComponent()
    7. 'Werte aus der Einstellung uebernehmen
    8. Me.Columns.Clear()
    9. DataGridSettings()
    10. 'Lese -und Schreibethread starten
    11. AlarmThread.IsBackground = True
    12. AlarmThread.Start()
    13. 'Me.DataSource = Alarmtable
    14. Me.DoubleBuffered = True
    15. RemoveHandler MyBase.Resize, AddressOf Alarmbox_Resize
    16. AddHandler MyBase.Resize, AddressOf Alarmbox_Resize
    17. End Sub


    Wäre über Tips echt dankbar


    @Rizzle Wahrscheinlich genügt es, das ganze Thread-Gedöns raus zu nehmen.
    Pack mal in die Zeilen nach dem Else von If (Me.InvokeRequired) Then einen Haltepunkt und überzeuge Dich davon, dass innerhalb einer Thread-Prozedur Me.InvokeRequired stets True ist.
    Was geschieht in den Prozeduren ResizeColumns, WriteAlarmbox, ClearAlarmbox, AlarmboxRefresh?
    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!
    Moin,

    da mache ich nichts besonderes schreibe in eine Datatable, Refresh das Control und lösche eine Datatable
    Wenn ich die auskommente Datatablesachen auskommentiere, steigt der Speicher immernoch an...

    VB.NET-Quellcode

    1. Private Sub WriteAlarmbox(Datetime As String, Group As String, Text As String)
    2. If Me.Columns.Count > 2 Then
    3. Main._SendRecieve.AlarmTable.Rows.Add(Datetime, Group, Text)
    4. End If
    5. End Sub
    6. Private Sub ClearAlarmbox()
    7. Try
    8. Main._SendRecieve.AlarmTable.Rows.Clear()
    9. Catch ex As Exception
    10. Log.Error(ex)
    11. ShowError(ex)
    12. End Try
    13. End Sub
    14. Private Sub AlarmboxRefresh()
    15. Try
    16. Me.Refresh()
    17. Catch ex As Exception
    18. Log.Error(ex)
    19. ShowError(ex)
    20. End Try
    21. End Sub
    @Rizzle Ist dieser permanente Aufruf erforderlich?
    Schmeiß mal das Thread-Gedöns raus, Du musst sowieso permanent invoken, und mach das in eine Timer-Tick-Prozedur.
    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!
    Ich hatte das vorher in einem Timer, dann frisst der den Speicher nicht. Dann ruckelt aber die Anwendung =/

    Der Städnige aufruf ist nötig weil die Datasource sich selbst ja leider nicht aktualisiert.

    Ich verstehe aber auch einfach nicht, wieso das Speicher frisst?

    Rizzle schrieb:

    Ich hatte das vorher in einem Timer, dann frisst der den Speicher nicht.
    Welches Intervall hatte denn der Timer?
    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!

    Rizzle schrieb:

    Der hat 1000 Milisekunden bekommen.
    Das Problem könnte sein, dass der nächste Tick schon da ist, bevor der aktuelle abgearbeitet ist.
    Halte in der Timer-Tick-Prozedur als erstes den Timer an und starte ihn als letztes wieder.
    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!