Initialisierung und Beendigung von Komponenten

Die Komponente wird von ihrem Konstruktor (SubNew in Visual Basic) initialisiert und zerstört von ihrem Destruktor (SubFinalize in Visual Basic). Der Konstruktor Ihrer Komponente wird aufgerufen, wenn eine Instanz Ihrer Komponente erstellt wird; der Konstruktor kann danach nicht aufgerufen werden. Der Destruktor wird kurz vor der Zerstörung Ihrer Komponente durch die Garbage Collection aufgerufen, und der von ihr belegte Arbeitsspeicher wird freigegeben.

Visual Basic-HinweisVisual Basic-Hinweis:

In früheren Versionen von Visual Basic hatten die Ereignisse Initialize und Terminate dieselbe Funktion wie der Konstruktor und der Destruktor.

Warten auf die Garbage Collection

Die Common Language Runtime ruft den Destruktor Ihrer Komponente auf, nachdem die Garbage Collection festgestellt hat, dass die Komponente nicht mehr von aktivem Code erreicht werden kann. Dies geschieht, wenn alle Verweise auf die Komponente freigegeben wurden oder wenn die einzigen Verweise auf Ihre Komponente von Objekten verwendet werden, die vom gesamten aktiven Code ähnlich isoliert sind, wie dies z. B. bei zyklischen Verweisen der Fall ist.

Da es zwischen dem Zeitpunkt, zu dem ein Benutzer die Arbeit an der Komponente beendet hat, und dem Zeitpunkt, zu dem ihr Destruktor aufgerufen wird, eine Verzögerung geben kann, wurde der Lebenszyklus von .NET Framework-Komponenten um einen zusätzlichen Schritt erweitert: Wenn Ihre Komponente Systemressourcen in Anspruch nimmt, z. B. Datenbankverbindungen oder Handles zu Windows-Systemobjekten, müssen Sie die IDisposable-Schnittstelle implementieren und eine Dispose-Methode bereitstellen, sodass der Benutzer Ihrer Komponente den Freigabezeitpunkt dieser Ressourcen wählen kann.

Lebenszyklus einer Komponente

Typeninitialisierung: Wenn die erste Instanz Ihrer Komponente erstellt wird, ist der als erstes ausgeführte Code ein gemeinsam genutzter Initialisieriungscode. Ein Verweis auf einen gemeinsam genutzten Member bewirkt außerdem, dass der gemeinsam genutzte Konstruktor ausgeführt wird. Dazu gehören alle initialisierten, gemeinsam genutzten Felder (Membervariablen) und der gemeinsam genutzte Konstruktor (Shared Sub New), falls vorhanden. Im folgenden Code wird für die gesamte Klasse eine Referenzschriftart erstellt.

Hinweis

Shared entspricht dem Schlüsselwort static in C#. Verwechseln Sie dies nicht mit dem Schlüsselwort Static in Visual Basic.

Public Class ADrawing
Shared ReadOnly ReferenceFont As New Font("TimesNewRoman", 14)
' Shared constructor does not overload other constructors.
Shared Sub New()
   ' There is no call to the base class's shared constructor.
   ' Insert code to initialize the shared data.
End Sub
End Class
class ADrawing
{
   static Font m_referenceFont = new Font("TimesNewRoman", 14);
   // Simply add the static keyword to create a static constructor.
   // Static constructors do not have any parameters.
   static ADrawing()
   {
      // There is no call to the base class's static constructor.
      // Code to initialize the font here.
   }
}

Hinweis

Eine Klasseninitialisierung kann auch dann auftreten, wenn keine Instanzen der Komponente erstellt werden.Beispielsweise wird eine abstract Klasse (MustInherit) mit freigegebenen Memberfunktionen initialisiert. Diese Funktionen sind für die Anwendung verfügbar, obwohl keine Instanz der Klasse erstellt wird.

  1. Instanzeninitialisierung: Wenn eine Instanz der Komponente erstellt wird, werden Datenmember mit Initialisierungscode initialisiert, und die entsprechende Konstruktorüberladung wird ausgeführt. Der folgende Code initialisiert ein privates Feld und definiert zwei Konstruktoren: Ein Konstruktor soll aufgerufen werden, wenn keine Parameter vorhanden sind, und der andere soll aufgerufen werden, wenn der Benutzer Parameter angibt.

    Class AShape
       Private answer As Integer = 42
       Public Sub New()
          ' Call another constructor with default initialization values.
          MyClass.New(System.Drawing.Color.Red, 5280, DefinedSizes.Large)
       End Sub
       Public Overloads Sub New(myColor As Color, myLength As Integer, _
                Size As DefinedSizes)
          ' Insert code to initialize the class.
       End Sub
       ' Defines the DefinedSizes enum
       Public Enum DefinedSizes
          Large
          Small
       End Enum
    End Class
    
    class AShape
    {
       private int m_answer = 42;
       // Forward to another constructor.
       public AShape() 
       : this(System.Drawing.Color.Red, 5280, DefinedSizes.Large)
       {
          // Additional initialization goes here.
       }
    
       public AShape(Color color, int length, DefinedSizes size)
       {
          // Code to initialize the class goes here.
       }
       // Defines the DefinedSizes enum
       public enum DefinedSizes
       {
          Large,
          Small
       }
    }
    
  2. Freigeben von Ressourcen: Wenn eine Komponente die IDisposable-Schnittstelle implementiert, muss sie eine Dispose-Methode bereitstellen, die vom Client aufgerufen werden soll, wenn die Verwendung der Komponente beendet wurde. Beachten Sie, dass jede Komponente, die von Component erbt, bereits eine Standardimplementierung von Dispose aufweist, die überschrieben werden kann, um zusätzlichen Bereinigungscode bereitzustellen. In der Dispose-Methode gibt die Komponente alle möglicherweise zugeordneten Systemressourcen sowie Verweise auf andere Objekte frei und macht sich selbst unbrauchbar. Es gibt möglicherweise auch Fälle, in denen die Komponente eine eigene Dispose-Methode aufrufen sollte. Der folgende Code verwirft ein abhängiges Objekt, das über eine Dispose-Methode verfügt.

    ' Assumes that the class implements IDisposable
    Public Sub Dispose() Implements IDisposable.Dispose
       myWidget.Dispose
       myWidget = Nothing
       ' Insert additional code.
    End Sub
    
    // Assumes that the class implements IDisposable
    public void IDisposable.Dispose()
    {
       mywidget.Dispose();
       mywidget = null;
       // Dispose of remaining objects.
    }
    
    

    Nach dem Aufruf von Dispose sollte der Client alle verbleibenden Verweise auf die Komponente freigeben, sodass die Garbage Collection den von der Komponente genutzten Speicher freigeben kann.

  3. Instance destruction: Wenn die Garbage Collection erkennt, dass keine verbleibenden Verweise auf die Komponente vorhanden sind, ruft die Laufzeit den Destruktor der Komponente Finalize(in Visual Basic) auf und gibt den Arbeitsspeicher frei. Um eigenen bereinigten Code zu implementieren, sollten Sie die Finalize-Methode der Basisklasse überschreiben (in Visual Basic) oder einen Destruktor implementieren (in Visual C#), aber immer einen Aufruf des Destruktors oder der Finalize-Methode der Basisklasse einschließen.

    Protected Overrides Sub Finalize()
       m_Gadget = Nothing
       m_Gear = Nothing
       MyBase.Finalize()
    End Sub
    
    // In C#, a destructor is used instead of a Finalize method.
    ~ThisClass()
    {
       m_gadget = null;
       m_gear = null;
       // The base class finalizer is called automatically
    }
    

Wann muss eine Dispose-Methode implementiert werden?

Wenn Ihre Komponente von Component erbt, wird eine Standardimplementierung von Dispose bereitgestellt. Diese Implementierung kann überschreiben werden, um einen angepassten Bereinigungscode zur Verfügung zu stellen. Wenn Sie Ihre Komponente über eine benutzerdefinierte Implementierung von IComponent erstellen, müssen Sie IDisposable implementieren, um eine Dispose-Methode für die Komponente bereitzustellen.

Sie müssen eine Dispose-Methode in Ihre Komponente implementieren, wenn sie Systemobjekte, Datenbankverbindungen oder andere knappen Ressourcen reserviert, die gleich freigegeben werden müssen, wenn die Komponente nicht mehr vom Benutzer benötigt wird.

Eine Dispose-Methode muss ebenfalls implementiert werden, wenn Ihre Komponente Verweise auf andere Objekte verwendet, die über Dispose-Methoden verfügen.

Wozu "Dispose" implementieren?

Abhängig von der Systemaktivität könnte zwischen dem Zeitpunkt, zu dem ein Benutzer Ihre Komponente nicht mehr benötigt, und dem Zeitpunkt, zu dem die Garbage Collection feststellt, dass der Code der Komponente nicht mehr erreichbar ist, ein nicht vorhersehbares Zeitintervall verstreichen. Wenn Sie keine Dispose-Methode bereitstellen, nimmt Ihre Komponente ihre Ressourcen während dieses Intervalls weiterhin in Anspruch.

Der ungünstigste Fall

Angenommen, es gäbe eine Serverkomponente, die eine Datenbankverbindung verwendet und keine Dispose-Methode besitzt. Auf einem Server mit viel Arbeitsspeicher könnten Sie viele Instanzen der Komponente erstellen und freigeben, ohne dass dies erhebliche Auswirkungen auf den freien Arbeitsspeicher haben würde. In diesem Fall würden die Komponenten wahrscheinlich eine Zeit lang, nachdem die Verweise darauf freigegeben wurden, nicht von der Garbage Collection zerstört.

Schließlich könnten alle verfügbaren Datenbankverbindungen von Komponenten belegt sein, die zwar freigegeben, aber nicht zerstört wurden. Selbst wenn der Server noch über genügend Arbeitsspeicher verfügen würde, könnte er keine Benutzeranforderungen beantworten.

Siehe auch

Aufgaben

Gewusst wie: Erstellen und Konfigurieren von Komponenten im Entwurfsmodus

Referenz

Dispose

Finalize

Konzepte

Merkmale der Komponentenklassen

Änderungen bei der Komponenteninstanziierung in Visual Basic