Thread richtig beenden wenn Programm terminiert wird

  • VB.NET
  • .NET (FX) 4.0

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

    Thread richtig beenden wenn Programm terminiert wird

    Hallo,

    ich erstelle derzeit ein Programm, von welchem aus Encodes für Videos angestoßen werden können, und da gerade das ziemlich viele Ressourcen frisst, möchte ich eben in meinem Programm auch anzeigen, wie viele das sind bzw wie viele verfügbar sind.

    Daher habe ich mir (vorerst) was simples gebastelt, welches mir alle 100ms die RAM-Auslastung in einer Progress-Bar aktualisiert.

    Dabei handelt es sich um eine eigene Komponente, die ich per Code in ein Panel packe (bei Programmstart wenn nicht per Config deaktiviert).

    Beende ich nun mein Programm (via x-Knopf eben) haut er mir nen Laufzeitfehler raus:


    Der entsprechende Code:

    Visual Basic-Quellcode

    1. Option Compare Binary
    2. Option Explicit On
    3. Option Infer On
    4. Option Strict On
    5. Imports System.ComponentModel
    6. Public Class ResourcesView
    7. Private Delegate Sub SetDeleg(ByVal ram As Integer)
    8. Private _fullRam As ULong
    9. Public Sub New()
    10. ' Designer instanciating
    11. InitializeComponent()
    12. ' Own instanciating
    13. AddHandlers()
    14. _fullRam = My.Computer.Info.TotalPhysicalMemory
    15. End Sub
    16. Private Sub AddHandlers()
    17. AddHandler Me.Load, AddressOf OnFormLoad
    18. End Sub
    19. Private Sub OnFormLoad(ByVal sender As Object, ByVal e As EventArgs)
    20. Dim bgThread As New Threading.Thread(New Threading.ThreadStart(
    21. Sub()
    22. While True
    23. Threading.Thread.Sleep(100)
    24. Dim ram As Integer = CalculateAvailabeRam()
    25. SetSub(ram)
    26. End While
    27. End Sub))
    28. bgThread.Start()
    29. End Sub
    30. Private Sub SetSub(ByVal ram As Integer)
    31. If Me.PRam.InvokeRequired Then
    32. Dim deleg As New SetDeleg(AddressOf SetSub)
    33. Me.Invoke(deleg, New Object() {ram})
    34. Else
    35. Me.PRam.Value = ram
    36. End If
    37. End Sub
    38. Private Function CalculateAvailabeRam() As Integer
    39. Dim usRam As ULong = My.Computer.Info.AvailablePhysicalMemory
    40. Dim avRam As ULong = _fullRam - usRam
    41. Dim ramP As Integer = CInt(Math.Round(avRam * 100 / _fullRam, 0))
    42. Return ramP
    43. End Function
    44. End Class


    Daher die Frage: Wie beende ich den Thread richtig, bevor er eben die Exception schmeißt, also dann, wenn ich die Anwendung schließe?

    Kagu-chan schrieb:

    Daher die Frage:
    Was ist Me.PRam?
    Poste bitte kompilierbare Quellen.
    Wie soll denn das Programm ablaufen?
    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!
    Mhm... war wohl zu lang nicht hier oder so... hier die fehlenden Daten:

    @Rainman:
    Weil ich (auch zu Übungszwecken) lieber mit selbsterstellten Threads arbeite als mit Timern. Finde Timer ohnehin unschön, warum kann ich aber nicht wirklich beantworten... :/

    @RodFromGermany:
    PRam ist eine ProgressBar, welche für die RAM-Anzeige zuständig ist.
    Wie meinst du das mit Compilierbare Quellen? Ich habs dir mal eben wo hochgeladen (das gesamte Projekt, ist noch sehr klein, gestern erst angefangen):
    puu.sh/dsef9/46b6d0fa1b.rar
    Das entsprechende Control findest du unter "Interface/Forms/ResourcesView.vb"

    Ablauf:
    Form wird erstellt, auf dieser sind entsprechende Panels. diesem Panel wird zu Programmstart, sofern in den Optionen nicht deaktiviert, das Control hinzugefügt.

    Quellcode

    1. Me.PRessources.Controls.Add(New ResourcesView)

    Die Logik zum nicht hinzufügen ist noch nicht drin.

    @fichz:
    Ich kann dir da ehrlich gesagt nicht ganz folgen... wie meinst du das als BackgroundThread?

    @ErfinderDesRades:
    Fehlerzeile:

    Visual Basic-Quellcode

    1. Me.Invoke(deleg, New Object() {ram})


    @WhitePage:
    Hat nicht funktioniert, hatte ein entsprechendes Beispiel zwar bei google gefunden (also den Ansatz), aber er hat meine Variable ignoriert... vermutlich eben wegen dem threading, wo ich noch recht neu bin (oder wieder, fast zwei jahre nicht mehr richtig mit VB gearbeitet)

    PRam ist eine ProgressBar, welche für die RAM-Anzeige zuständig ist.
    nun, in dieser Zeile kann die Fehlermeldung nur ein einziges Objekt betreffen, denn in der Zeile kommt nur ein Objekt vor, was disposed werden kann: Me.
    Im Grunde verstehe ich die Frage nicht: es ist doch offensichtlich, dass beim Programm-Ende Me disposed ist, und wenn Me disposed ist, muss die Zeile natürlich crashen, denn ein disposetes Form kann natürlich nix invoken.
    Oder?

    Lösungsmöglichkeiten sind ja bereits genannt.
    Einfach vor den Thread als Background setzen (wird dann automatisch beim Beenden des Hauptthreads mitbeendet).

    VB.NET-Quellcode

    1. bgThread.IsBackground = True
    2. bgThread.Start()


    und im SetSub einfach abfragen ob die Form noch vorhanden ist:

    VB.NET-Quellcode

    1. If Me.IsDisposed() Then Return
    2. If Me.PRam.InvokeRequired Then
    3. ' ....


    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten

    fichz schrieb:

    Einfach vor den Thread als Background setzen (wird dann automatisch beim Beenden des Hauptthreads mitbeendet).

    Sehr gute Lösung solange dieser nicht irgendwas macht, was du selbst beenden willst oder die Kontrolle behalten willst.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    OK, das mit dem Background hatte ich jetzt nicht wörtlich genommen, wusste davon auch nichts.

    Hab es jetzt auch hinbekommen indem ich mir meine Relevanten Threads in ne Extra klasse packt die auf meine Event-Klasse äugelt (quasi ne Komponente die dafür da ist Anwendungsweite Events zu feuern, wenn sie in mehreren Kontexten gebraucht werden, Threads wissen jetzt wann sie ruhig sein sollen)

    Ist halt auch daher notwendig, da ich einige der Threading-Geschichten deaktivieren können möchte zur Laufzeit, oder auch neu startet etc...
    Brauche daher tatsächlich eben die volle Kontrolle über das Teil

    Kagu-chan schrieb:

    Wie meinst du das mit Compilierbare Quellen?
    Wenn Du einen größeren Snippet hochlädtst, und wir Deinen Effekt reproduzieren wollen, sollte der Snippet mit einem Minimum an Aufwand kompilierfähig gemacht werden können.
    Hieße die Variable ProgressBar1, wäre das problemlos gegangen.
    Also:
    Selbst in ein Projekt reinkopieren und alles, weas Du tust, um es kompilierbar zu machen, reinschreiben, z.B. die verwendeten Controls benennen. ;)
    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!