none
Wird ein laufender Thread, für den keine Referenz mehr existiert, vom Garbage-Collector disposed? RRS feed

  • Frage

  • Hi,

    folgendes Minimal-Beispiel:

    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            StartThread()
        End Sub
    
        Public Sub Work()
            System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite) 'Endloses Sleep
        End Sub
    
        Public Sub StartThread()
            Dim t As New Threading.Thread(AddressOf Work)
            t.Start()
        End Sub
    
    End Class

    Könnte es sein, dass der GC irgendwann den erstellten Thread entfernt?

    Ich finde in der MSDN auch keinen Hinweis darüber, ob eventuell irgendwo anders noch eine Referenz auf den Thread besteht (auch wenn ich vermute, dass dies der Fall ist, denn sonst könnte er ja nicht intern verwaltet werden, oder?) .
    Denn wenn das so ist, dann würde der GC den Thread ja nicht einsammeln...

    Danke

    Momo




    Freitag, 1. Juni 2012 18:18

Antworten

  • Hallo Momo,

    nein, ein gestarteter Thread wird nicht vom GC aufgeräumt.
    Aus Sicht des GC ist er ein Root-Object und wird von diesem verwaltet,
    u. a.  da der GC alle Threads für eine Garbage Collection anhalten muss,
    siehe Thread.Suspend, Garbage Collection und Sicherungspunkte

    Das dem so ist, kannst Du leicht prüfen, in dem Du versuchst Dein "Programm" zu beenden.
    Da Du einen Vordergrund-Thread gestartet hast, siehe Vordergrund- und Hintergrundthreads -
    läuft das Programm weiter, wie Du im Task Manager sehen kannst, und muss dort "gekillt" werden,
    um es loszuwerden. Damit so was (bei richtigen Programmen) nicht passiert:
    Setze IsBackground auf True, oder verwende für Kurzläufer den ThreadPool.

    Gruß Elmar

    • Als Antwort vorgeschlagen Ellen Ramcke Samstag, 2. Juni 2012 12:52
    • Als Antwort markiert Mohamed Kari Sonntag, 3. Juni 2012 19:13
    Samstag, 2. Juni 2012 06:18
    Beantworter

Alle Antworten

  • Hallo Momo,

    nein, ein gestarteter Thread wird nicht vom GC aufgeräumt.
    Aus Sicht des GC ist er ein Root-Object und wird von diesem verwaltet,
    u. a.  da der GC alle Threads für eine Garbage Collection anhalten muss,
    siehe Thread.Suspend, Garbage Collection und Sicherungspunkte

    Das dem so ist, kannst Du leicht prüfen, in dem Du versuchst Dein "Programm" zu beenden.
    Da Du einen Vordergrund-Thread gestartet hast, siehe Vordergrund- und Hintergrundthreads -
    läuft das Programm weiter, wie Du im Task Manager sehen kannst, und muss dort "gekillt" werden,
    um es loszuwerden. Damit so was (bei richtigen Programmen) nicht passiert:
    Setze IsBackground auf True, oder verwende für Kurzläufer den ThreadPool.

    Gruß Elmar

    • Als Antwort vorgeschlagen Ellen Ramcke Samstag, 2. Juni 2012 12:52
    • Als Antwort markiert Mohamed Kari Sonntag, 3. Juni 2012 19:13
    Samstag, 2. Juni 2012 06:18
    Beantworter
  • Hallo Elmar,

    Deine Antwort ist - wie alle - sachlich richtig. Was mich stört und das fällt mir in diesem Beispiel besonders auf, dass die Doku von msdn teilweise sehr oberflächlich ist. Was ist denn jetzt wieder ein Sicherungspunkt? Das wird nicht erklärt. Ich finde, das Thema threading wird in msdn nicht umfassend behandelt und erklärt.

    Hast Du vielleicht eine Literatur Quelle mit den Themen

    • Multitasking von Windows
    • Bilder und Zeitdiegramme zum Threading
    • Arbeitsweise Threading
    • Methoden und Threading

    Das wäre super

    Gruss Ellen


    Ich benutze/ I'm using VB2008 & VB2010

    Samstag, 2. Juni 2012 13:03
  • Hallo Ellen,

    nicht nur die MSDN ist dort knapp gehalten, auch ich hatte aus meiner Antwort vieles wieder gestrichen.
    Was mich angeht: In einem Forum Beitrag kann man in der zeit schlicht und einfach nicht so viel schreiben,
    dass es annähernd vollständig würde und ich habe mich schließlich auf den Wirkung beschränkt
    (so wie man Aspirin bei Kopfschmerz nimmt, ohne sich über die Wirkungsweise vonAcetylsalicylsäure zu informieren ;-)

    Was die MSDN angeht: Dort ist zu spüren, das Multi-threaded für Anwendungsentwickler (im Vergleich zu Systementwicklern)
    ein relativ neues Feld ist, da Multi-Core Prozessoren erst seit wenigen Jahren allgemein verfügbar sind.
    Dies wird sich mit Sicherheit langsam bessern, da die immer mehr auf Threading gesetzt wird,
    nicht nur für .NET auch bei Windows selbst (WinRT für Metro). Als Teaser:
    Async made simple in Windows 8, with C# and Visual Basic
    und Future directions for C# and Visual Basic (neben einigem mehr; Suche nach async)

    Zur Frage selbst:

    Threading ist integraler Kern-Bestandteil des Betriebssystems und die Dokumentation dazu sollte man lesen.
    .NETs (managed) Thread setzt darauf auf und stellt nur eine dünne Hülle dafür bereit.
    Meine Aussage, dass der GC Threads verwaltet, war für die Antwort auf .NET hin stark vereinfacht.
    Vielmehr arbeitet die Laufzeit dort eng mit verzahnt mit dem OS zusammen.

    Threading ist ein sehr komplexes Thema, da Menschen (auch wenn manche anderes behaupten)
    meiner Erfahrung nicht wirklich zwei unabhängige Dinge gleichzeitig tun können (Prozessoren schon).

    Mit "Bildern und Zeitdiagrammen" sprichst Du etwas an, was man bei Multi-threading gerade nicht so einfach
    herzeigen kann (ohne stark bis zu unzulässig zu vereinfachen).

    Denn man redet nicht umsonst dabei von "nebenläufiger" Programmierung.
    Und wie es bei Läufern auf der Aschenbahn ist, so sind die Zeiten sehr unterschiedlich:
    der eine startet schnell, der zweite wird langsam warm und dem nächsten geht kurz vor Schluß die Puste aus.
    Wer die Ziellinie als Erster überschreitet lässt sich erst am Ende sagen.
    Und wenn man beim Staffellauf den Stab übergeben muss, wird es noch komplizierter -
    was entfernt passiert, wenn zwei Threads Daten austauschen müssen.

    Zum Safe-point:

    Das ist ein Konstrukt, das notwendig ist, weil der GC die realen Speicheradressen von Objekten verschiebt.
    Damit er das gefahrlos tun kann, müssen die Threads auf einen definierten Zustand haben,
    bei dem sich keine Adressen ändern. Um das zu Erreichen gibt es unterschiedliche Methoden,
    wie Thread-Hijacking, das Einfügen von speziellen Anweisungen (durch den Jitter) uam.
    Siehe http://stackoverflow.com/questions/8404245/gc-behavior-and-clr-thread-hijacking

    Für den Otto-Normalprogrammierer - der ich meistens auch bin - reicht es zu wissen, dass der GC es "richtig" macht.

    Ich ende hier bewusst.
    Willst Du richtig in die Tiefe gehen, wäre ein Buch wie Concurrent Programming on Windows ein Möglichkeit.
    Als Warnung: Da gibt es wenige Bilder - siehe Leseprobe - hier gilt: Eine Zeile Code sagt mehr als 1000 Bilder -
    was mir als altgedientem Entwickler auch am sympathischsten ist ;-)

    Der andere Weg (den ich meist empfehle): sich an ausgesuchten Stellen in das Thema einzuarbeiten.

    Gruß Elmar

    Samstag, 2. Juni 2012 18:31
    Beantworter
  • Danke für deine Mühe. Das hat mir sehr geholfen :)

    Momentan versuche ich mich am Exception-Handling beim Threading. Das wirft doch einige Fragen auf... Aber ich glaube, ich dafür besser einen Thread (no pun intented) auf...

    Sonntag, 3. Juni 2012 19:26